From f95ab265c10ba1497bf5865752a9750f29a3fb0b Mon Sep 17 00:00:00 2001 From: skull132 Date: Wed, 4 Jun 2014 18:20:49 +0300 Subject: [PATCH] Bay Update 02 --- aurora.dme | 20 + .../components/trinary_devices/filter.dm | 47 +- .../components/trinary_devices/mixer.dm | 90 + code/ATMOSPHERICS/mainspipe.dm | 707 + code/TriDimension/Turfs.dm | 9 +- .../Cael_Aislinn/ShieldGen/energy_field.dm | 4 + .../ShieldGen/shield_capacitor.dm | 45 +- .../Cael_Aislinn/ShieldGen/shield_gen.dm | 107 +- .../ShieldGen/shield_gen_external.dm | 4 +- code/WorkInProgress/Chinsky/ashtray.dm | 1 + .../Sigyn/Softcurity/wardrobe.dm | 6 +- code/WorkInProgress/SkyMarshal/wardrobes.dm | 4 +- code/WorkInProgress/Tastyfish/Eliza_Data.dm | 4 +- code/WorkInProgress/autopsy.dm | 2 +- code/WorkInProgress/kilakk/fax.dm | 2 + code/__HELPERS/global_lists.dm | 9 +- code/__HELPERS/unsorted.dm | 18 +- code/_onclick/adjacent.dm | 22 +- code/_onclick/click.dm | 10 +- code/_onclick/hud/screen_objects.dm | 31 +- code/controllers/configuration.dm | 17 +- code/controllers/master_controller.dm | 11 +- code/controllers/voting.dm | 7 +- code/datums/ai_laws.dm | 5 + code/datums/datacore.dm | 7 +- code/datums/datumvars.dm | 14 +- code/datums/helper_datums/getrev.dm | 2 +- code/datums/mind.dm | 2 +- code/datums/spells/ethereal_jaunt.dm | 5 + code/datums/spells/horsemask.dm | 19 +- code/datums/supplypacks.dm | 50 +- code/defines/obj.dm | 2 +- code/defines/obj/hydro.dm | 8 +- code/defines/obj/weapon.dm | 10 +- code/game/area/Space Station 13 areas.dm | 48 +- code/game/atoms.dm | 53 +- code/game/dna/dna2.dm | 21 +- code/game/dna/dna2_helpers.dm | 4 + code/game/dna/dna_modifier.dm | 37 +- code/game/dna/genes/monkey.dm | 6 +- code/game/gamemodes/changeling/changeling.dm | 2 + .../gamemodes/changeling/changeling_powers.dm | 76 + .../gamemodes/changeling/modularchangling.dm | 22 +- code/game/gamemodes/game_mode.dm | 5 +- code/game/gamemodes/gameticker.dm | 10 + .../game/gamemodes/malfunction/malfunction.dm | 2 +- code/game/gamemodes/objective.dm | 2 +- .../gamemodes/revolution/rp-revolution.dm | 6 +- .../gamemodes/revolution/rp_revolution.dm | 2 +- code/game/gamemodes/setupgame.dm | 6 +- code/game/gamemodes/wizard/soulstone.dm | 6 - code/game/gamemodes/wizard/spellbook.dm | 2 +- code/game/jobs/job/civilian.dm | 4 +- code/game/jobs/job/medical.dm | 10 +- code/game/jobs/job/science.dm | 16 +- code/game/machinery/adv_med.dm | 5 +- code/game/machinery/alarm.dm | 271 +- code/game/machinery/atmoalter/canister.dm | 9 +- code/game/machinery/bees_items.dm | 11 +- code/game/machinery/bots/ed209bot.dm | 8 +- code/game/machinery/bots/farmbot.dm | 10 +- code/game/machinery/bots/medbot.dm | 4 +- code/game/machinery/bots/secbot.dm | 6 +- code/game/machinery/camera/camera.dm | 2 +- code/game/machinery/camera/motion.dm | 4 +- code/game/machinery/cell_charger.dm | 11 +- code/game/machinery/cloning.dm | 10 +- .../machinery/computer/HolodeckControl.dm | 4 +- code/game/machinery/computer/aifixer.dm | 35 +- code/game/machinery/computer/arcade.dm | 21 +- .../game/machinery/computer/buildandrepair.dm | 9 +- code/game/machinery/computer/card.dm | 59 +- code/game/machinery/computer/cloning.dm | 1 + code/game/machinery/computer/computer.dm | 5 + code/game/machinery/computer/medical.dm | 33 +- code/game/machinery/computer/pod.dm | 12 +- code/game/machinery/computer/robot.dm | 7 +- code/game/machinery/computer/security.dm | 25 +- code/game/machinery/computer/skills.dm | 8 +- .../machinery/doors/airlock_electronics.dm | 20 +- code/game/machinery/hologram.dm | 9 +- code/game/machinery/igniter.dm | 6 +- code/game/machinery/kitchen/smartfridge.dm | 316 +- code/game/machinery/machinery.dm | 14 +- code/game/machinery/pipe/construction.dm | 84 +- code/game/machinery/pipe/pipe_dispenser.dm | 3 + code/game/machinery/telecomms/broadcaster.dm | 89 +- .../machinery/telecomms/telecomunications.dm | 4 +- code/game/machinery/vending.dm | 41 +- code/game/mecha/equipment/weapons/weapons.dm | 9 +- code/game/mecha/mech_fabricator.dm | 47 +- code/game/mecha/mecha_construction_paths.dm | 4 +- code/game/objects/closets/secure/research.dm | 2 +- code/game/objects/effects/aliens.dm | 10 +- .../objects/effects/decals/Cleanable/fuel.dm | 2 +- .../objects/effects/decals/posters/bs12.dm | 101 + code/game/objects/explosion.dm | 34 +- code/game/objects/items.dm | 13 +- code/game/objects/items/bodybag.dm | 1 + code/game/objects/items/devices/PDA/PDA.dm | 22 +- code/game/objects/items/devices/PDA/cart.dm | 2 +- code/game/objects/items/devices/flashlight.dm | 23 + code/game/objects/items/devices/megaphone.dm | 2 +- code/game/objects/items/devices/paicard.dm | 205 +- .../objects/items/devices/pipe_painter.dm | 8 +- .../game/objects/items/devices/radio/radio.dm | 18 +- code/game/objects/items/devices/scanners.dm | 2 +- .../objects/items/devices/taperecorder.dm | 12 +- code/game/objects/items/devices/uplinks.dm | 2 +- code/game/objects/items/robot/robot_items.dm | 11 +- code/game/objects/items/stacks/medical.dm | 4 +- .../game/objects/items/stacks/sheets/glass.dm | 12 +- .../objects/items/stacks/sheets/mineral.dm | 10 + .../items/stacks/sheets/sheet_types.dm | 11 +- code/game/objects/items/stacks/stack.dm | 2 +- code/game/objects/items/toys.dm | 12 +- code/game/objects/items/trash.dm | 2 +- code/game/objects/items/weapons/AI_modules.dm | 14 + code/game/objects/items/weapons/cards_ids.dm | 8 +- .../objects/items/weapons/cigs_lighters.dm | 7 +- .../items/weapons/implants/implanter.dm | 10 +- code/game/objects/items/weapons/manuals.dm | 926 +- .../objects/items/weapons/storage/backpack.dm | 15 +- .../objects/items/weapons/storage/bags.dm | 4 +- .../objects/items/weapons/storage/belt.dm | 29 - .../objects/items/weapons/storage/bible.dm | 3 +- .../objects/items/weapons/storage/boxes.dm | 18 +- .../items/weapons/storage/briefcase.dm | 1 + .../objects/items/weapons/storage/firstaid.dm | 25 +- .../objects/items/weapons/storage/internal.dm | 85 + .../objects/items/weapons/storage/misc.dm | 9 + .../objects/items/weapons/storage/secure.dm | 8 +- .../objects/items/weapons/storage/storage.dm | 92 +- .../items/weapons/storage/uplink_kits.dm | 18 + code/game/objects/items/weapons/tools.dm | 26 +- code/game/objects/items/weapons/weaponry.dm | 4 +- code/game/objects/structures/bedsheet_bin.dm | 2 +- .../closets/secure/guncabinet.dm | 2 +- .../crates_lockers/closets/secure/personal.dm | 22 + .../closets/secure/scientist.dm | 2 +- .../crates_lockers/closets/wardrobe.dm | 4 +- code/game/objects/structures/grille.dm | 6 + code/game/objects/structures/inflatable.dm | 307 + code/game/objects/structures/musician.dm | 6 +- code/game/objects/structures/transit_tubes.dm | 10 +- code/game/objects/structures/window.dm | 20 +- code/game/socket_talk.dm | 2 +- code/game/sound.dm | 140 +- code/game/supplyshuttle.dm | 36 +- code/game/turfs/simulated.dm | 10 +- code/game/turfs/simulated/floor.dm | 10 +- code/game/turfs/simulated/floor_types.dm | 2 +- code/game/turfs/simulated/walls.dm | 24 +- code/game/turfs/simulated/walls_reinforced.dm | 26 +- code/game/turfs/space/space.dm | 4 +- code/game/verbs/who.dm | 35 +- code/global.dm | 3 +- code/modules/admin/admin.dm | 26 +- code/modules/admin/admin_verbs.dm | 75 +- code/modules/admin/create_object.dm | 5 +- code/modules/admin/player_notes.dm | 13 + code/modules/admin/verbs/adminhelp.dm | 6 +- code/modules/admin/verbs/adminpm.dm | 103 +- code/modules/admin/verbs/deadsay.dm | 2 +- code/modules/admin/verbs/one_click_antag.dm | 10 +- code/modules/admin/verbs/randomverbs.dm | 31 + code/modules/admin/verbs/vox_raiders.dm | 7 +- code/modules/client/client defines.dm | 5 + code/modules/client/client procs.dm | 18 +- code/modules/client/preferences.dm | 59 +- code/modules/client/preferences_savefile.dm | 20 +- code/modules/clothing/clothing.dm | 204 +- code/modules/clothing/gloves/stungloves.dm | 100 +- code/modules/clothing/head/helmet.dm | 3 +- code/modules/clothing/head/misc_special.dm | 2 + code/modules/clothing/masks/breath.dm | 11 +- code/modules/clothing/shoes/miscellaneous.dm | 2 + code/modules/clothing/spacesuits/alien.dm | 14 +- code/modules/clothing/spacesuits/captain.dm | 2 +- .../clothing/spacesuits/miscellaneous.dm | 2 +- code/modules/clothing/spacesuits/rig.dm | 18 +- code/modules/clothing/suits/armor.dm | 2 +- code/modules/clothing/suits/bio.dm | 2 +- code/modules/clothing/suits/jobs.dm | 3 +- code/modules/clothing/suits/labcoat.dm | 38 +- code/modules/clothing/suits/miscellaneous.dm | 2 +- code/modules/clothing/suits/storage.dm | 29 + code/modules/clothing/suits/utility.dm | 8 +- code/modules/clothing/under/chameleon.dm | 468 +- .../clothing/under/jobs/engineering.dm | 5 +- code/modules/clothing/under/jobs/medsci.dm | 4 +- code/modules/clothing/under/miscellaneous.dm | 4 +- code/modules/clothing/under/ties.dm | 213 +- code/modules/detectivework/detective_work.dm | 610 +- code/modules/detectivework/evidence.dm | 2 +- code/modules/economy/ATM.dm | 56 +- code/modules/economy/EFTPOS.dm | 52 +- code/modules/economy/cash.dm | 14 +- code/modules/events/infestation.dm | 12 +- code/modules/ext_scripts/irc.dm | 7 +- code/modules/food/recipes_microwave.dm | 6 + code/modules/library/lib_items.dm | 8 +- code/modules/mining/mine_items.dm | 24 +- code/modules/mining/mine_turfs.dm | 4 +- code/modules/mining/minerals.dm | 12 +- code/modules/mining/satchel_ore_boxdm.dm | 3 +- code/modules/mob/dead/observer/observer.dm | 9 + code/modules/mob/death.dm | 6 + code/modules/mob/emote.dm | 18 + code/modules/mob/hear_say.dm | 162 + code/modules/mob/holder.dm | 51 + code/modules/mob/living/carbon/alien/alien.dm | 2 +- .../mob/living/carbon/alien/humanoid/life.dm | 4 +- .../mob/living/carbon/alien/larva/life.dm | 4 +- .../mob/living/carbon/brain/brain_item.dm | 2 +- code/modules/mob/living/carbon/brain/life.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 19 +- code/modules/mob/living/carbon/human/human.dm | 198 +- .../mob/living/carbon/human/human_damage.dm | 6 + .../mob/living/carbon/human/human_defense.dm | 2 +- .../mob/living/carbon/human/human_defines.dm | 10 + .../mob/living/carbon/human/inventory.dm | 53 +- code/modules/mob/living/carbon/human/life.dm | 206 +- code/modules/mob/living/carbon/human/say.dm | 220 +- .../mob/living/carbon/human/update_icons.dm | 231 +- .../modules/mob/living/carbon/monkey/diona.dm | 101 +- .../modules/mob/living/carbon/monkey/emote.dm | 11 +- code/modules/mob/living/carbon/monkey/life.dm | 28 +- .../mob/living/carbon/monkey/monkey.dm | 20 +- code/modules/mob/living/carbon/species.dm | 136 +- code/modules/mob/living/living.dm | 39 +- code/modules/mob/living/living_defense.dm | 2 +- code/modules/mob/living/say.dm | 382 +- code/modules/mob/living/silicon/ai/ai.dm | 118 +- code/modules/mob/living/silicon/alarm.dm | 111 + .../modules/mob/living/silicon/pai/examine.dm | 2 +- code/modules/mob/living/silicon/pai/life.dm | 2 +- .../modules/mob/living/silicon/pai/recruit.dm | 258 +- code/modules/mob/living/silicon/pai/say.dm | 2 +- .../mob/living/silicon/pai/software.dm | 158 +- .../mob/living/silicon/robot/component.dm | 14 +- .../mob/living/silicon/robot/drone/drone.dm | 349 + .../silicon/robot/drone/drone_abilities.dm | 48 + .../silicon/robot/drone/drone_console.dm | 124 + .../silicon/robot/drone/drone_damage.dm | 24 + .../living/silicon/robot/drone/drone_items.dm | 349 + .../silicon/robot/drone/drone_manufacturer.dm | 141 + .../mob/living/silicon/robot/examine.dm | 5 +- code/modules/mob/living/silicon/robot/life.dm | 92 +- .../modules/mob/living/silicon/robot/robot.dm | 87 +- .../mob/living/silicon/robot/robot_modules.dm | 61 + code/modules/mob/living/silicon/say.dm | 167 +- code/modules/mob/living/silicon/silicon.dm | 97 +- code/modules/mob/living/simple_animal/bees.dm | 8 +- .../modules/mob/living/simple_animal/borer.dm | 8 +- .../mob/living/simple_animal/constructs.dm | 10 +- .../simple_animal/friendly/spiderbot.dm | 5 +- code/modules/mob/living/simple_animal/head.dm | 3 +- .../mob/living/simple_animal/hostile/mimic.dm | 2 +- .../mob/living/simple_animal/parrot.dm | 53 + .../modules/mob/living/simple_animal/shade.dm | 1 + .../mob/living/simple_animal/simple_animal.dm | 23 +- code/modules/mob/living/simple_animal/worm.dm | 1 + code/modules/mob/login.dm | 4 +- code/modules/mob/mob.dm | 2 - code/modules/mob/new_player/login.dm | 1 + code/modules/mob/new_player/new_player.dm | 25 +- .../mob/new_player/preferences_setup.dm | 63 +- .../mob/new_player/sprite_accessories.dm | 84 +- code/modules/mob/say.dm | 26 +- code/modules/organs/organ.dm | 43 +- code/modules/organs/organ_external.dm | 18 +- code/modules/organs/organ_internal.dm | 6 +- code/modules/paperwork/carbonpaper.dm | 50 + code/modules/paperwork/filingcabinet.dm | 8 +- code/modules/paperwork/folders.dm | 9 +- code/modules/paperwork/paper.dm | 87 +- code/modules/paperwork/paper_bundle.dm | 247 + code/modules/paperwork/paperbin.dm | 21 +- code/modules/paperwork/photocopier.dm | 138 +- code/modules/paperwork/photography.dm | 10 +- code/modules/power/apc.dm | 12 +- code/modules/power/cable.dm | 72 +- code/modules/power/lighting.dm | 2 +- code/modules/power/pacman2.dm | 2 +- code/modules/power/turbine.dm | 3 + code/modules/projectiles/ammunition.dm | 2 +- code/modules/projectiles/ammunition/boxes.dm | 14 + .../modules/projectiles/ammunition/bullets.dm | 6 + code/modules/projectiles/gun.dm | 4 +- code/modules/projectiles/guns/alien.dm | 168 + .../projectiles/guns/projectile/bow.dm | 86 +- .../projectiles/guns/projectile/pneumatic.dm | 82 + .../projectiles/guns/projectile/shotgun.dm | 2 +- .../modules/projectiles/projectile/bullets.dm | 6 +- code/modules/projectiles/projectile/change.dm | 6 +- code/modules/projectiles/targeting.dm | 4 +- code/modules/reagents/Chemistry-Holder.dm | 24 +- code/modules/reagents/Chemistry-Machinery.dm | 33 +- .../Chemistry-Reagents-Antidepressants.dm | 25 - code/modules/reagents/Chemistry-Reagents.dm | 2 +- code/modules/reagents/Chemistry-Recipes.dm | 7 +- code/modules/reagents/reagent_containers.dm | 2 +- .../reagents/reagent_containers/borghydro.dm | 7 +- .../reagents/reagent_containers/dropper.dm | 1 + .../reagent_containers/food/drinks.dm | 12 + .../food/drinks/drinkingglass.dm | 8 +- .../reagent_containers/food/snacks.dm | 18 +- .../reagents/reagent_containers/glass.dm | 7 + .../reagents/reagent_containers/pill.dm | 13 + .../reagents/reagent_containers/spray.dm | 75 +- .../reagents/reagent_containers/syringes.dm | 17 +- code/modules/reagents/reagent_dispenser.dm | 14 + code/modules/reagents/syringe_gun.dm | 12 +- code/modules/recycling/disposal.dm | 42 +- code/modules/recycling/sortingmachinery.dm | 4 +- code/modules/research/designs.dm | 9 + code/modules/research/rd-readme.dm | 2 +- code/modules/research/rdconsole.dm | 36 +- code/modules/research/research_shuttle.dm | 23 +- code/modules/research/server.dm | 31 +- .../research/xenoarchaeology/chemistry.dm | 2 +- .../research/xenoarchaeology/manuals.dm | 239 +- .../xenoarchaeology/tools/tools_anoscanner.dm | 2 +- .../tools/tools_depthscanner.dm | 2 +- code/modules/supermatter/supermatter.dm | 13 +- code/modules/virus2/analyser.dm | 48 +- code/modules/virus2/centrifuge.dm | 245 +- code/modules/virus2/curer.dm | 8 +- code/modules/virus2/disease2.dm | 33 +- code/modules/virus2/diseasesplicer.dm | 202 +- code/modules/virus2/dishincubator.dm | 244 +- code/modules/virus2/isolator.dm | 300 +- code/modules/virus2/items_devices.dm | 69 +- code/setup.dm | 27 +- code/unused/computer2/peripherals.dm | 2 +- code/world.dm | 84 +- html/changelog.html | 59 +- html/loading.gif | Bin 0 -> 1633 bytes html/painew.png | Bin 0 -> 3545 bytes icons/effects/contamination.dmi | Bin 679 -> 709 bytes icons/effects/species.dmi | Bin 25355 -> 22538 bytes icons/mob/custom-synthetic.dmi | Bin 116808 -> 188295 bytes icons/mob/head.dmi | Bin 119763 -> 120983 bytes icons/mob/human.dmi | Bin 10775 -> 12474 bytes icons/mob/human_face.dmi | Bin 39689 -> 49941 bytes icons/mob/human_races/r_armalis.dmi | Bin 0 -> 4073 bytes icons/mob/human_races/r_def_lizard.dmi | Bin 2315 -> 1833 bytes icons/mob/human_races/r_def_tajaran.dmi | Bin 1866 -> 1881 bytes icons/mob/human_races/r_diona.dmi | Bin 14986 -> 2650 bytes icons/mob/human_races/r_lizard.dmi | Bin 5665 -> 1820 bytes icons/mob/human_races/r_tajaran.dmi | Bin 2236 -> 2226 bytes icons/mob/items_lefthand.dmi | Bin 152074 -> 154261 bytes icons/mob/items_righthand.dmi | Bin 154098 -> 155812 bytes icons/mob/robots.dmi | Bin 137797 -> 145111 bytes icons/mob/screen1_White.dmi | Bin 128124 -> 128151 bytes icons/mob/species/armalis/feet.dmi | Bin 0 -> 369 bytes icons/mob/species/armalis/gloves.dmi | Bin 0 -> 377 bytes icons/mob/species/armalis/head.dmi | Bin 0 -> 385 bytes icons/mob/species/armalis/held.dmi | Bin 0 -> 996 bytes icons/mob/species/armalis/suit.dmi | Bin 0 -> 2665 bytes icons/mob/species/vox/feet.dmi | Bin 0 -> 362 bytes icons/mob/species/vox/gloves.dmi | Bin 0 -> 358 bytes icons/mob/species/vox/head.dmi | Bin 0 -> 1997 bytes icons/mob/species/vox/mask.dmi | Bin 0 -> 702 bytes icons/mob/species/vox/suit.dmi | Bin 0 -> 3171 bytes icons/mob/suit.dmi | Bin 253752 -> 261408 bytes icons/mob/uniform.dmi | Bin 213181 -> 240063 bytes icons/obj/atmospherics/m_filter.dmi | Bin 0 -> 9912 bytes icons/obj/atmospherics/m_mixer.dmi | Bin 0 -> 9677 bytes icons/obj/atmospherics/mainspipe.dmi | Bin 40902 -> 40943 bytes icons/obj/atmospherics/t_mixer.dmi | Bin 0 -> 10666 bytes icons/obj/bureaucracy.dmi | Bin 9405 -> 10562 bytes icons/obj/clothing/gloves.dmi | Bin 10559 -> 10763 bytes icons/obj/clothing/masks.dmi | Bin 13045 -> 13689 bytes icons/obj/clothing/shoes.dmi | Bin 8525 -> 8651 bytes icons/obj/clothing/suits.dmi | Bin 84367 -> 87529 bytes icons/obj/clothing/ties_overlay.dmi | Bin 0 -> 3091 bytes icons/obj/clothing/uniforms.dmi | Bin 54649 -> 54652 bytes icons/obj/contraband.dmi | Bin 63294 -> 92737 bytes icons/obj/device.dmi | Bin 21468 -> 21872 bytes icons/obj/doors/Doorphoron.dmi | Bin 0 -> 14673 bytes icons/obj/gun.dmi | Bin 44809 -> 45945 bytes icons/obj/inflatable.dmi | Bin 0 -> 17220 bytes icons/obj/items.dmi | Bin 66709 -> 66868 bytes icons/obj/janitor.dmi | Bin 14104 -> 10662 bytes icons/obj/machines/drone_fab.dmi | Bin 0 -> 1289 bytes icons/obj/objects.dmi | Bin 116695 -> 117195 bytes icons/obj/pipe-item.dmi | Bin 19944 -> 24070 bytes icons/obj/podwindows.dmi | Bin 10170 -> 6904 bytes icons/obj/storage.dmi | Bin 55632 -> 55857 bytes icons/obj/weapons.dmi | Bin 20756 -> 22314 bytes icons/pda_icons/pda_atmos.png | Bin 2839 -> 224 bytes icons/pda_icons/pda_back.png | Bin 2848 -> 219 bytes icons/pda_icons/pda_bell.png | Bin 2842 -> 226 bytes icons/pda_icons/pda_blank.png | Bin 2805 -> 189 bytes icons/pda_icons/pda_boom.png | Bin 2847 -> 241 bytes icons/pda_icons/pda_bucket.png | Bin 2837 -> 220 bytes icons/pda_icons/pda_chatroom.png | Bin 2845 -> 223 bytes icons/pda_icons/pda_crate.png | Bin 2849 -> 234 bytes icons/pda_icons/pda_cuffs.png | Bin 2848 -> 225 bytes icons/pda_icons/pda_eject.png | Bin 2839 -> 226 bytes icons/pda_icons/pda_exit.png | Bin 2846 -> 241 bytes icons/pda_icons/pda_flashlight.png | Bin 2836 -> 221 bytes icons/pda_icons/pda_honk.png | Bin 2834 -> 219 bytes icons/pda_icons/pda_locked.PNG | Bin 2840 -> 215 bytes icons/pda_icons/pda_mail.png | Bin 2830 -> 216 bytes icons/pda_icons/pda_medical.png | Bin 2817 -> 203 bytes icons/pda_icons/pda_menu.png | Bin 2838 -> 229 bytes icons/pda_icons/pda_mule.png | Bin 2846 -> 230 bytes icons/pda_icons/pda_notes.png | Bin 2833 -> 218 bytes icons/pda_icons/pda_power.png | Bin 2833 -> 215 bytes icons/pda_icons/pda_rdoor.png | Bin 2828 -> 212 bytes icons/pda_icons/pda_reagent.png | Bin 2832 -> 219 bytes icons/pda_icons/pda_refresh.png | Bin 2849 -> 234 bytes icons/pda_icons/pda_scanner.png | Bin 2852 -> 241 bytes icons/pda_icons/pda_signaler.png | Bin 2850 -> 238 bytes icons/pda_icons/pda_status.png | Bin 2847 -> 230 bytes icons/turf/areas.dmi | Bin 21472 -> 21756 bytes interface/skin.dmf | 12 + maps/backup/tgstation2.dmm | 12524 +++++++++++++++ maps/tgstation2.dmm | 12681 ++++++++-------- nano/js/nano_base_helpers.js | 88 +- nano/templates/disease_splicer.tmpl | 108 + nano/templates/dish_incubator.tmpl | 123 + nano/templates/isolation_centrifuge.tmpl | 81 + nano/templates/pathogenic_isolator.tmpl | 107 + nano/templates/smartfridge.tmpl | 79 + sound/effects/basscannon.ogg | Bin 0 -> 16772 bytes sound/misc/nymphchirp.ogg | Bin 0 -> 6270 bytes sound/voice/shriek1.ogg | Bin 0 -> 27819 bytes tools/mapmerge/1prepare_map.bat | 6 + tools/mapmerge/2clean_map.bat | 5 + tools/mapmerge/MapPatcher.jar | Bin 10136 -> 10738 bytes tools/mapmerge/clean_map_git.sh | 9 + tools/mapmerge/install.txt | 4 +- 436 files changed, 30324 insertions(+), 10747 deletions(-) create mode 100644 code/ATMOSPHERICS/mainspipe.dm create mode 100644 code/game/objects/items/weapons/storage/internal.dm create mode 100644 code/game/objects/items/weapons/storage/misc.dm create mode 100644 code/game/objects/structures/inflatable.dm create mode 100644 code/modules/clothing/suits/storage.dm create mode 100644 code/modules/mob/hear_say.dm create mode 100644 code/modules/mob/holder.dm create mode 100644 code/modules/mob/living/silicon/alarm.dm create mode 100644 code/modules/mob/living/silicon/robot/drone/drone.dm create mode 100644 code/modules/mob/living/silicon/robot/drone/drone_abilities.dm create mode 100644 code/modules/mob/living/silicon/robot/drone/drone_console.dm create mode 100644 code/modules/mob/living/silicon/robot/drone/drone_damage.dm create mode 100644 code/modules/mob/living/silicon/robot/drone/drone_items.dm create mode 100644 code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm create mode 100644 code/modules/paperwork/carbonpaper.dm create mode 100644 code/modules/paperwork/paper_bundle.dm create mode 100644 code/modules/projectiles/guns/alien.dm create mode 100644 html/loading.gif create mode 100644 html/painew.png create mode 100644 icons/mob/human_races/r_armalis.dmi create mode 100644 icons/mob/species/armalis/feet.dmi create mode 100644 icons/mob/species/armalis/gloves.dmi create mode 100644 icons/mob/species/armalis/head.dmi create mode 100644 icons/mob/species/armalis/held.dmi create mode 100644 icons/mob/species/armalis/suit.dmi create mode 100644 icons/mob/species/vox/feet.dmi create mode 100644 icons/mob/species/vox/gloves.dmi create mode 100644 icons/mob/species/vox/head.dmi create mode 100644 icons/mob/species/vox/mask.dmi create mode 100644 icons/mob/species/vox/suit.dmi create mode 100644 icons/obj/atmospherics/m_filter.dmi create mode 100644 icons/obj/atmospherics/m_mixer.dmi create mode 100644 icons/obj/atmospherics/t_mixer.dmi create mode 100644 icons/obj/clothing/ties_overlay.dmi create mode 100644 icons/obj/doors/Doorphoron.dmi create mode 100644 icons/obj/inflatable.dmi create mode 100644 icons/obj/machines/drone_fab.dmi create mode 100644 maps/backup/tgstation2.dmm create mode 100644 nano/templates/disease_splicer.tmpl create mode 100644 nano/templates/dish_incubator.tmpl create mode 100644 nano/templates/isolation_centrifuge.tmpl create mode 100644 nano/templates/pathogenic_isolator.tmpl create mode 100644 nano/templates/smartfridge.tmpl create mode 100644 sound/effects/basscannon.ogg create mode 100644 sound/misc/nymphchirp.ogg create mode 100644 sound/voice/shriek1.ogg create mode 100644 tools/mapmerge/1prepare_map.bat create mode 100644 tools/mapmerge/2clean_map.bat create mode 100644 tools/mapmerge/clean_map_git.sh diff --git a/aurora.dme b/aurora.dme index d86f02a8..6e8d1759 100644 --- a/aurora.dme +++ b/aurora.dme @@ -22,6 +22,9 @@ #define FILE_DIR "icons/misc" #define FILE_DIR "icons/mob" #define FILE_DIR "icons/mob/human_races" +#define FILE_DIR "icons/mob/species" +#define FILE_DIR "icons/mob/species/armalis" +#define FILE_DIR "icons/mob/species/vox" #define FILE_DIR "icons/obj" #define FILE_DIR "icons/obj/assemblies" #define FILE_DIR "icons/obj/atmospherics" @@ -121,6 +124,7 @@ #include "code\ATMOSPHERICS\datum_pipe_network.dm" #include "code\ATMOSPHERICS\datum_pipeline.dm" #include "code\ATMOSPHERICS\he_pipes.dm" +#include "code\ATMOSPHERICS\mainspipe.dm" #include "code\ATMOSPHERICS\pipes.dm" #include "code\ATMOSPHERICS\components\portables_connector.dm" #include "code\ATMOSPHERICS\components\tvalve.dm" @@ -629,7 +633,9 @@ #include "code\game\objects\items\weapons\storage\briefcase.dm" #include "code\game\objects\items\weapons\storage\fancy.dm" #include "code\game\objects\items\weapons\storage\firstaid.dm" +#include "code\game\objects\items\weapons\storage\internal.dm" #include "code\game\objects\items\weapons\storage\lockbox.dm" +#include "code\game\objects\items\weapons\storage\misc.dm" #include "code\game\objects\items\weapons\storage\secure.dm" #include "code\game\objects\items\weapons\storage\storage.dm" #include "code\game\objects\items\weapons\storage\toolbox.dm" @@ -651,6 +657,7 @@ #include "code\game\objects\structures\flora.dm" #include "code\game\objects\structures\girders.dm" #include "code\game\objects\structures\grille.dm" +#include "code\game\objects\structures\inflatable.dm" #include "code\game\objects\structures\janicart.dm" #include "code\game\objects\structures\kitchen_spike.dm" #include "code\game\objects\structures\ladders.dm" @@ -832,6 +839,7 @@ #include "code\modules\clothing\suits\jobs.dm" #include "code\modules\clothing\suits\labcoat.dm" #include "code\modules\clothing\suits\miscellaneous.dm" +#include "code\modules\clothing\suits\storage.dm" #include "code\modules\clothing\suits\utility.dm" #include "code\modules\clothing\suits\wiz_robe.dm" #include "code\modules\clothing\under\chameleon.dm" @@ -923,6 +931,8 @@ #include "code\modules\mob\abilities.dm" #include "code\modules\mob\death.dm" #include "code\modules\mob\emote.dm" +#include "code\modules\mob\hear_say.dm" +#include "code\modules\mob\holder.dm" #include "code\modules\mob\inventory.dm" #include "code\modules\mob\language.dm" #include "code\modules\mob\login.dm" @@ -1026,6 +1036,7 @@ #include "code\modules\mob\living\carbon\monkey\monkey.dm" #include "code\modules\mob\living\carbon\monkey\powers.dm" #include "code\modules\mob\living\carbon\monkey\update_icons.dm" +#include "code\modules\mob\living\silicon\alarm.dm" #include "code\modules\mob\living\silicon\death.dm" #include "code\modules\mob\living\silicon\login.dm" #include "code\modules\mob\living\silicon\say.dm" @@ -1069,6 +1080,12 @@ #include "code\modules\mob\living\silicon\robot\robot_modules.dm" #include "code\modules\mob\living\silicon\robot\robot_movement.dm" #include "code\modules\mob\living\silicon\robot\wires.dm" +#include "code\modules\mob\living\silicon\robot\drone\drone.dm" +#include "code\modules\mob\living\silicon\robot\drone\drone_abilities.dm" +#include "code\modules\mob\living\silicon\robot\drone\drone_console.dm" +#include "code\modules\mob\living\silicon\robot\drone\drone_damage.dm" +#include "code\modules\mob\living\silicon\robot\drone\drone_items.dm" +#include "code\modules\mob\living\silicon\robot\drone\drone_manufacturer.dm" #include "code\modules\mob\living\simple_animal\bees.dm" #include "code\modules\mob\living\simple_animal\borer.dm" #include "code\modules\mob\living\simple_animal\constructs.dm" @@ -1123,11 +1140,13 @@ #include "code\modules\organs\organ_internal.dm" #include "code\modules\organs\pain.dm" #include "code\modules\organs\wound.dm" +#include "code\modules\paperwork\carbonpaper.dm" #include "code\modules\paperwork\clipboard.dm" #include "code\modules\paperwork\filingcabinet.dm" #include "code\modules\paperwork\folders.dm" #include "code\modules\paperwork\handlabeler.dm" #include "code\modules\paperwork\paper.dm" +#include "code\modules\paperwork\paper_bundle.dm" #include "code\modules\paperwork\paperbin.dm" #include "code\modules\paperwork\pen.dm" #include "code\modules\paperwork\photocopier.dm" @@ -1173,6 +1192,7 @@ #include "code\modules\projectiles\targeting.dm" #include "code\modules\projectiles\ammunition\boxes.dm" #include "code\modules\projectiles\ammunition\bullets.dm" +#include "code\modules\projectiles\guns\alien.dm" #include "code\modules\projectiles\guns\energy.dm" #include "code\modules\projectiles\guns\projectile.dm" #include "code\modules\projectiles\guns\energy\erifles.dm" diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm index 0320f899..5ea2c0eb 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm @@ -14,7 +14,7 @@ obj/machinery/atmospherics/trinary/filter /* Filter types: -1: Nothing - 0: Carbon Molecules: Plasma Toxin, Oxygen Agent B + 0: Plasma: Plasma Toxin, Oxygen Agent B 1: Oxygen: Oxygen ONLY 2: Nitrogen: Nitrogen ONLY 3: Carbon Dioxide: Carbon Dioxide ONLY @@ -170,7 +170,7 @@ obj/machinery/atmospherics/trinary/filter/attack_hand(user as mob) // -- TLE var/current_filter_type switch(filter_type) if(0) - current_filter_type = "Carbon Molecules" + current_filter_type = "Plasma" if(1) current_filter_type = "Oxygen" if(2) @@ -188,7 +188,7 @@ obj/machinery/atmospherics/trinary/filter/attack_hand(user as mob) // -- TLE Power: [on?"On":"Off"]
Filtering: [current_filter_type]

Set Filter Type:

- Carbon Molecules
+ Plasma
Oxygen
Nitrogen
Carbon Dioxide
@@ -234,4 +234,45 @@ obj/machinery/atmospherics/trinary/filter/Topic(href, href_list) // -- TLE */ return +obj/machinery/atmospherics/trinary/filter/m_filter + icon = 'icons/obj/atmospherics/m_filter.dmi' + icon_state = "intact_off" + dir = SOUTH + initialize_directions = SOUTH|NORTH|EAST + +obj/machinery/atmospherics/trinary/filter/m_filter/New() + ..() + switch(dir) + if(NORTH) + initialize_directions = WEST|NORTH|SOUTH + if(SOUTH) + initialize_directions = SOUTH|EAST|NORTH + if(EAST) + initialize_directions = EAST|WEST|NORTH + if(WEST) + initialize_directions = WEST|SOUTH|EAST + +obj/machinery/atmospherics/trinary/filter/m_filter/initialize() + if(node1 && node2 && node3) return + + var/node1_connect = turn(dir, -180) + var/node2_connect = turn(dir, 90) + var/node3_connect = dir + + for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect)) + if(target.initialize_directions & get_dir(target,src)) + node1 = target + break + + for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect)) + if(target.initialize_directions & get_dir(target,src)) + node2 = target + break + + for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect)) + if(target.initialize_directions & get_dir(target,src)) + node3 = target + break + + update_icon() diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm index 026d8406..54a43075 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm @@ -160,3 +160,93 @@ obj/machinery/atmospherics/trinary/mixer src.update_icon() src.updateUsrDialog() return + +obj/machinery/atmospherics/trinary/mixer/t_mixer + icon = 'icons/obj/atmospherics/t_mixer.dmi' + icon_state = "intact_off" + + dir = SOUTH + initialize_directions = SOUTH|EAST|WEST + + //node 3 is the outlet, nodes 1 & 2 are intakes + +obj/machinery/atmospherics/trinary/mixer/t_mixer/New() + ..() + switch(dir) + if(NORTH) + initialize_directions = EAST|NORTH|WEST + if(SOUTH) + initialize_directions = SOUTH|WEST|EAST + if(EAST) + initialize_directions = EAST|NORTH|SOUTH + if(WEST) + initialize_directions = WEST|NORTH|SOUTH + +obj/machinery/atmospherics/trinary/mixer/t_mixer/initialize() + if(node1 && node2 && node3) return + + var/node1_connect = turn(dir, -90) + var/node2_connect = turn(dir, 90) + var/node3_connect = dir + + for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect)) + if(target.initialize_directions & get_dir(target,src)) + node1 = target + break + + for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect)) + if(target.initialize_directions & get_dir(target,src)) + node2 = target + break + + for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect)) + if(target.initialize_directions & get_dir(target,src)) + node3 = target + break + + update_icon() + +obj/machinery/atmospherics/trinary/mixer/m_mixer + icon = 'icons/obj/atmospherics/m_mixer.dmi' + icon_state = "intact_off" + + dir = SOUTH + initialize_directions = SOUTH|NORTH|EAST + + //node 3 is the outlet, nodes 1 & 2 are intakes + +obj/machinery/atmospherics/trinary/mixer/m_mixer/New() + ..() + switch(dir) + if(NORTH) + initialize_directions = WEST|NORTH|SOUTH + if(SOUTH) + initialize_directions = SOUTH|EAST|NORTH + if(EAST) + initialize_directions = EAST|WEST|NORTH + if(WEST) + initialize_directions = WEST|SOUTH|EAST + +obj/machinery/atmospherics/trinary/mixer/m_mixer/initialize() + if(node1 && node2 && node3) return + + var/node1_connect = turn(dir, -180) + var/node2_connect = turn(dir, 90) + var/node3_connect = dir + + for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect)) + if(target.initialize_directions & get_dir(target,src)) + node1 = target + break + + for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect)) + if(target.initialize_directions & get_dir(target,src)) + node2 = target + break + + for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect)) + if(target.initialize_directions & get_dir(target,src)) + node3 = target + break + + update_icon() \ No newline at end of file diff --git a/code/ATMOSPHERICS/mainspipe.dm b/code/ATMOSPHERICS/mainspipe.dm new file mode 100644 index 00000000..631f3530 --- /dev/null +++ b/code/ATMOSPHERICS/mainspipe.dm @@ -0,0 +1,707 @@ +// internal pipe, don't actually place or use these +obj/machinery/atmospherics/pipe/mains_component + var/obj/machinery/atmospherics/mains_pipe/parent_pipe + var/list/obj/machinery/atmospherics/pipe/mains_component/nodes = new() + + New(loc) + ..(loc) + parent_pipe = loc + + check_pressure(pressure) + var/datum/gas_mixture/environment = loc.loc.return_air() + + var/pressure_difference = pressure - environment.return_pressure() + + if(pressure_difference > parent_pipe.maximum_pressure) + mains_burst() + + else if(pressure_difference > parent_pipe.fatigue_pressure) + //TODO: leak to turf, doing pfshhhhh + if(prob(5)) + mains_burst() + + else return 1 + + pipeline_expansion() + return nodes + + disconnect(obj/machinery/atmospherics/reference) + if(nodes.Find(reference)) + nodes.Remove(reference) + + proc/mains_burst() + parent_pipe.burst() + +obj/machinery/atmospherics/mains_pipe + icon = 'icons/obj/atmospherics/mainspipe.dmi' + layer = 2.4 //under wires with their 2.5 + + force = 20 + + var/volume = 0 + + var/alert_pressure = 80*ONE_ATMOSPHERE + + var/initialize_mains_directions = 0 + + var/list/obj/machinery/atmospherics/mains_pipe/nodes = new() + var/obj/machinery/atmospherics/pipe/mains_component/supply + var/obj/machinery/atmospherics/pipe/mains_component/scrubbers + var/obj/machinery/atmospherics/pipe/mains_component/aux + + var/minimum_temperature_difference = 300 + var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No + + var/maximum_pressure = 70*ONE_ATMOSPHERE + var/fatigue_pressure = 55*ONE_ATMOSPHERE + alert_pressure = 55*ONE_ATMOSPHERE + + New() + ..() + + supply = new(src) + supply.volume = volume + supply.nodes.len = nodes.len + scrubbers = new(src) + scrubbers.volume = volume + scrubbers.nodes.len = nodes.len + aux = new(src) + aux.volume = volume + aux.nodes.len = nodes.len + + hide(var/i) + if(level == 1 && istype(loc, /turf/simulated)) + invisibility = i ? 101 : 0 + update_icon() + + proc/burst() + ..() + for(var/obj/machinery/atmospherics/pipe/mains_component/pipe in contents) + burst() + + proc/check_pressure(pressure) + var/datum/gas_mixture/environment = loc.return_air() + + var/pressure_difference = pressure - environment.return_pressure() + + if(pressure_difference > maximum_pressure) + burst() + + else if(pressure_difference > fatigue_pressure) + //TODO: leak to turf, doing pfshhhhh + if(prob(5)) + burst() + + else return 1 + + disconnect() + ..() + for(var/obj/machinery/atmospherics/pipe/mains_component/node in nodes) + node.disconnect() + + Del() + disconnect() + ..() + + initialize() + for(var/i = 1 to nodes.len) + var/obj/machinery/atmospherics/mains_pipe/node = nodes[i] + if(node) + supply.nodes[i] = node.supply + scrubbers.nodes[i] = node.scrubbers + aux.nodes[i] = node.aux + +obj/machinery/atmospherics/mains_pipe/simple + name = "mains pipe" + desc = "A one meter section of 3-line mains pipe" + + dir = SOUTH + initialize_mains_directions = SOUTH|NORTH + + New() + nodes.len = 2 + ..() + switch(dir) + if(SOUTH || NORTH) + initialize_mains_directions = SOUTH|NORTH + if(EAST || WEST) + initialize_mains_directions = EAST|WEST + if(NORTHEAST) + initialize_mains_directions = NORTH|EAST + if(NORTHWEST) + initialize_mains_directions = NORTH|WEST + if(SOUTHEAST) + initialize_mains_directions = SOUTH|EAST + if(SOUTHWEST) + initialize_mains_directions = SOUTH|WEST + + proc/normalize_dir() + if(dir==3) + dir = 1 + else if(dir==12) + dir = 4 + + update_icon() + if(nodes[1] && nodes[2]) + icon_state = "intact[invisibility ? "-f" : "" ]" + + //var/node1_direction = get_dir(src, node1) + //var/node2_direction = get_dir(src, node2) + + //dir = node1_direction|node2_direction + + else + if(!nodes[1]&&!nodes[2]) + del(src) //TODO: silent deleting looks weird + var/have_node1 = nodes[1]?1:0 + var/have_node2 = nodes[2]?1:0 + icon_state = "exposed[have_node1][have_node2][invisibility ? "-f" : "" ]" + + initialize() + normalize_dir() + var/node1_dir + var/node2_dir + + for(var/direction in cardinal) + if(direction&initialize_mains_directions) + if (!node1_dir) + node1_dir = direction + else if (!node2_dir) + node2_dir = direction + + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node1_dir)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[1] = target + break + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node2_dir)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[2] = target + break + + ..() // initialize internal pipes + + var/turf/T = src.loc // hide if turf is not intact + hide(T.intact) + update_icon() + + hidden + level = 1 + icon_state = "intact-f" + + visible + level = 2 + icon_state = "intact" + +obj/machinery/atmospherics/mains_pipe/manifold + name = "manifold pipe" + desc = "A manifold composed of mains pipes" + + dir = SOUTH + initialize_mains_directions = EAST|NORTH|WEST + volume = 105 + + New() + nodes.len = 3 + ..() + initialize_mains_directions = (NORTH|SOUTH|EAST|WEST) & ~dir + + initialize() + var/connect_directions = initialize_mains_directions + + for(var/direction in cardinal) + if(direction&connect_directions) + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,direction)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[1] = target + connect_directions &= ~direction + break + if (nodes[1]) + break + + + for(var/direction in cardinal) + if(direction&connect_directions) + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,direction)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[2] = target + connect_directions &= ~direction + break + if (nodes[2]) + break + + + for(var/direction in cardinal) + if(direction&connect_directions) + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,direction)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[3] = target + connect_directions &= ~direction + break + if (nodes[3]) + break + + ..() // initialize internal pipes + + var/turf/T = src.loc // hide if turf is not intact + hide(T.intact) + update_icon() + + update_icon() + icon_state = "manifold[invisibility ? "-f" : "" ]" + + hidden + level = 1 + icon_state = "manifold-f" + + visible + level = 2 + icon_state = "manifold" + +obj/machinery/atmospherics/mains_pipe/manifold4w + name = "manifold pipe" + desc = "A manifold composed of mains pipes" + + dir = SOUTH + initialize_mains_directions = EAST|NORTH|WEST|SOUTH + volume = 105 + + New() + nodes.len = 4 + ..() + + initialize() + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,NORTH)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[1] = target + break + + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,SOUTH)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[2] = target + break + + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,EAST)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[3] = target + break + + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,WEST)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[3] = target + break + + ..() // initialize internal pipes + + var/turf/T = src.loc // hide if turf is not intact + hide(T.intact) + update_icon() + + update_icon() + icon_state = "manifold4w[invisibility ? "-f" : "" ]" + + hidden + level = 1 + icon_state = "manifold4w-f" + + visible + level = 2 + icon_state = "manifold4w" + +obj/machinery/atmospherics/mains_pipe/split + name = "mains splitter" + desc = "A splitter for connecting to a single pipe off a mains." + + var/obj/machinery/atmospherics/pipe/mains_component/split_node + var/obj/machinery/atmospherics/node3 + var/icon_type + + New() + nodes.len = 2 + ..() + initialize_mains_directions = turn(dir, 90) | turn(dir, -90) + initialize_directions = dir // actually have a normal connection too + + initialize() + var/node1_dir + var/node2_dir + var/node3_dir + + node1_dir = turn(dir, 90) + node2_dir = turn(dir, -90) + node3_dir = dir + + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node1_dir)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[1] = target + break + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node2_dir)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[2] = target + break + for(var/obj/machinery/atmospherics/target in get_step(src,node3_dir)) + if(target.initialize_directions & get_dir(target,src)) + node3 = target + break + + ..() // initialize internal pipes + + // bind them + spawn(5) + if(node3 && split_node) + var/datum/pipe_network/N1 = node3.return_network(src) + var/datum/pipe_network/N2 = split_node.return_network(split_node) + if(N1 && N2) + N1.merge(N2) + + var/turf/T = src.loc // hide if turf is not intact + hide(T.intact) + update_icon() + + update_icon() + icon_state = "split-[icon_type][invisibility ? "-f" : "" ]" + + return_network(A) + return split_node.return_network(A) + + supply + icon_type = "supply" + + New() + ..() + split_node = supply + + hidden + level = 1 + icon_state = "split-supply-f" + + visible + level = 2 + icon_state = "split-supply" + + scrubbers + icon_type = "scrubbers" + + New() + ..() + split_node = scrubbers + + hidden + level = 1 + icon_state = "split-scrubbers-f" + + visible + level = 2 + icon_state = "split-scrubbers" + + aux + icon_type = "aux" + + New() + ..() + split_node = aux + + hidden + level = 1 + icon_state = "split-aux-f" + + visible + level = 2 + icon_state = "split-aux" + +obj/machinery/atmospherics/mains_pipe/split3 + name = "triple mains splitter" + desc = "A splitter for connecting to the 3 pipes on a mainline." + + var/obj/machinery/atmospherics/supply_node + var/obj/machinery/atmospherics/scrubbers_node + var/obj/machinery/atmospherics/aux_node + + New() + nodes.len = 1 + ..() + initialize_mains_directions = dir + initialize_directions = cardinal & ~dir // actually have a normal connection too + + initialize() + var/node1_dir + var/supply_node_dir + var/scrubbers_node_dir + var/aux_node_dir + + node1_dir = dir + aux_node_dir = turn(dir, 180) + if(dir & (NORTH|SOUTH)) + supply_node_dir = EAST + scrubbers_node_dir = WEST + else + supply_node_dir = SOUTH + scrubbers_node_dir = NORTH + + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src, node1_dir)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[1] = target + break + for(var/obj/machinery/atmospherics/target in get_step(src,supply_node_dir)) + if(target.initialize_directions & get_dir(target,src)) + supply_node = target + break + for(var/obj/machinery/atmospherics/target in get_step(src,scrubbers_node_dir)) + if(target.initialize_directions & get_dir(target,src)) + scrubbers_node = target + break + for(var/obj/machinery/atmospherics/target in get_step(src,aux_node_dir)) + if(target.initialize_directions & get_dir(target,src)) + aux_node = target + break + + ..() // initialize internal pipes + + // bind them + spawn(5) + if(supply_node) + var/datum/pipe_network/N1 = supply_node.return_network(src) + var/datum/pipe_network/N2 = supply.return_network(supply) + if(N1 && N2) + N1.merge(N2) + if(scrubbers_node) + var/datum/pipe_network/N1 = scrubbers_node.return_network(src) + var/datum/pipe_network/N2 = scrubbers.return_network(scrubbers) + if(N1 && N2) + N1.merge(N2) + if(aux_node) + var/datum/pipe_network/N1 = aux_node.return_network(src) + var/datum/pipe_network/N2 = aux.return_network(aux) + if(N1 && N2) + N1.merge(N2) + + var/turf/T = src.loc // hide if turf is not intact + hide(T.intact) + update_icon() + + update_icon() + icon_state = "split-t[invisibility ? "-f" : "" ]" + + return_network(obj/machinery/atmospherics/reference) + var/obj/machinery/atmospherics/A + + A = supply_node.return_network(reference) + if(!A) + A = scrubbers_node.return_network(reference) + if(!A) + A = aux_node.return_network(reference) + + return A + + hidden + level = 1 + icon_state = "split-t-f" + + visible + level = 2 + icon_state = "split-t" + +obj/machinery/atmospherics/mains_pipe/cap + name = "pipe cap" + desc = "A cap for the end of a mains pipe" + + dir = SOUTH + initialize_directions = SOUTH + volume = 35 + + New() + nodes.len = 1 + ..() + initialize_mains_directions = dir + + update_icon() + icon_state = "cap[invisibility ? "-f" : ""]" + + initialize() + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,dir)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[1] = target + break + + ..() + + var/turf/T = src.loc // hide if turf is not intact + hide(T.intact) + update_icon() + + hidden + level = 1 + icon_state = "cap-f" + + visible + level = 2 + icon_state = "cap" + +//TODO: Get Mains valves working! +/* +obj/machinery/atmospherics/mains_pipe/valve + icon_state = "mvalve0" + + name = "mains shutoff valve" + desc = "A mains pipe valve" + + var/open = 1 + + dir = SOUTH + initialize_mains_directions = SOUTH|NORTH + + New() + nodes.len = 2 + ..() + initialize_mains_directions = dir | turn(dir, 180) + + update_icon(animation) + var/turf/simulated/floor = loc + var/hide = istype(floor) ? floor.intact : 0 + level = 1 + for(var/obj/machinery/atmospherics/mains_pipe/node in nodes) + if(node.level == 2) + hide = 0 + level = 2 + break + + if(animation) + flick("[hide?"h":""]mvalve[src.open][!src.open]",src) + else + icon_state = "[hide?"h":""]mvalve[open]" + + initialize() + normalize_dir() + var/node1_dir + var/node2_dir + + for(var/direction in cardinal) + if(direction&initialize_mains_directions) + if (!node1_dir) + node1_dir = direction + else if (!node2_dir) + node2_dir = direction + + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node1_dir)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[1] = target + break + for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node2_dir)) + if(target.initialize_mains_directions & get_dir(target,src)) + nodes[2] = target + break + + if(open) + ..() // initialize internal pipes + + update_icon() + + proc/normalize_dir() + if(dir==3) + dir = 1 + else if(dir==12) + dir = 4 + + proc/open() + if(open) return 0 + + open = 1 + update_icon() + + initialize() + + return 1 + + proc/close() + if(!open) return 0 + + open = 0 + update_icon() + + for(var/obj/machinery/atmospherics/pipe/mains_component/node in src) + for(var/obj/machinery/atmospherics/pipe/mains_component/o in node.nodes) + o.disconnect(node) + o.build_network() + + return 1 + + attack_ai(mob/user as mob) + return + + attack_paw(mob/user as mob) + return attack_hand(user) + + attack_hand(mob/user as mob) + src.add_fingerprint(usr) + update_icon(1) + sleep(10) + if (open) + close() + else + open() + + digital // can be controlled by AI + name = "digital mains valve" + desc = "A digitally controlled valve." + icon_state = "dvalve0" + + attack_ai(mob/user as mob) + return src.attack_hand(user) + + attack_hand(mob/user as mob) + if(!src.allowed(user)) + user << "\red Access denied." + return + ..() + + //Radio remote control + + proc + set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + if(frequency) + radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA) + + var/frequency = 0 + var/id = null + var/datum/radio_frequency/radio_connection + + initialize() + ..() + if(frequency) + set_frequency(frequency) + + update_icon(animation) + var/turf/simulated/floor = loc + var/hide = istype(floor) ? floor.intact : 0 + level = 1 + for(var/obj/machinery/atmospherics/mains_pipe/node in nodes) + if(node.level == 2) + hide = 0 + level = 2 + break + + if(animation) + flick("[hide?"h":""]dvalve[src.open][!src.open]",src) + else + icon_state = "[hide?"h":""]dvalve[open]" + + receive_signal(datum/signal/signal) + if(!signal.data["tag"] || (signal.data["tag"] != id)) + return 0 + + switch(signal.data["command"]) + if("valve_open") + if(!open) + open() + + if("valve_close") + if(open) + close() + + if("valve_toggle") + if(open) + close() + else + open() +*/ \ No newline at end of file diff --git a/code/TriDimension/Turfs.dm b/code/TriDimension/Turfs.dm index 94114c9a..ae7bf820 100644 --- a/code/TriDimension/Turfs.dm +++ b/code/TriDimension/Turfs.dm @@ -53,6 +53,13 @@ H:updatehealth() return ..() +/turf/proc/hasbelow() + var/turf/controllerlocation = locate(1, 1, z) + for(var/obj/effect/landmark/zcontroller/controller in controllerlocation) + if(controller.down) + return 1 + return 0 + /turf/simulated/floor/open/proc/getbelow() var/turf/controllerlocation = locate(1, 1, z) for(var/obj/effect/landmark/zcontroller/controller in controllerlocation) @@ -73,7 +80,7 @@ //overwrite the attackby of space to transform it to openspace if necessary /turf/space/attackby(obj/item/C as obj, mob/user as mob) - if (istype(C, /obj/item/weapon/cable_coil)) + if (istype(C, /obj/item/weapon/cable_coil) && src.hasbelow()) var/turf/simulated/floor/open/W = src.ChangeTurf(/turf/simulated/floor/open) W.attackby(C, user) return diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/energy_field.dm b/code/WorkInProgress/Cael_Aislinn/ShieldGen/energy_field.dm index a5519fbf..b9b8c24c 100644 --- a/code/WorkInProgress/Cael_Aislinn/ShieldGen/energy_field.dm +++ b/code/WorkInProgress/Cael_Aislinn/ShieldGen/energy_field.dm @@ -11,6 +11,7 @@ density = 0 invisibility = 101 var/strength = 0 + var/ticks_recovering = 10 /obj/effect/energy_field/ex_act(var/severity) Stress(0.5 + severity) @@ -27,9 +28,12 @@ strength -= severity //if we take too much damage, drop out - the generator will bring us back up if we have enough power + ticks_recovering = min(ticks_recovering + 2, 10) if(strength < 1) invisibility = 101 density = 0 + ticks_recovering = 10 + strength = 0 else if(strength >= 1) invisibility = 0 density = 1 diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_capacitor.dm b/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_capacitor.dm index 25825c48..b95c0ffb 100644 --- a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_capacitor.dm +++ b/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_capacitor.dm @@ -9,12 +9,10 @@ icon_state = "capacitor" var/active = 1 density = 1 - anchored = 1 var/stored_charge = 0 var/time_since_fail = 100 - var/max_charge = 1000000 - var/max_charge_rate = 100000 - var/min_charge_rate = 0 + var/max_charge = 5e6 + var/charge_limit = 200000 var/locked = 0 // use_power = 1 //0 use nothing @@ -23,6 +21,7 @@ idle_power_usage = 10 active_power_usage = 100 var/charge_rate = 100 + var/obj/machinery/shield_gen/owned_gen /obj/machinery/shield_capacitor/New() spawn(10) @@ -55,17 +54,17 @@ src.anchored = !src.anchored src.visible_message("\blue \icon[src] [src] has been [anchored ? "bolted to the floor" : "unbolted from the floor"] by [user].") - spawn(0) - for(var/obj/machinery/shield_gen/gen in range(1, src)) - if(get_dir(src, gen) == src.dir) - if(!src.anchored && gen.owned_capacitor == src) - gen.owned_capacitor = null - break - else if(src.anchored && !gen.owned_capacitor) - gen.owned_capacitor = src - break - gen.updateDialog() - updateDialog() + if(anchored) + spawn(0) + for(var/obj/machinery/shield_gen/gen in range(1, src)) + if(get_dir(src, gen) == src.dir && !gen.owned_capacitor) + owned_gen = gen + owned_gen.owned_capacitor = src + owned_gen.updateDialog() + else + if(owned_gen && owned_gen.owned_capacitor == src) + owned_gen.owned_capacitor = null + owned_gen = null else ..() @@ -94,17 +93,19 @@ t += "[time_since_fail > 2 ? "Charging stable." : "Warning, low charge!"]
" t += "Charge: [stored_charge] Watts ([100 * stored_charge/max_charge]%)
" t += "Charge rate: \ - \[min\] \ + \[----\] \ + \[---\] \ \[--\] \ \[-\][charge_rate] Watts/sec \ \[+\] \ \[++\] \ - \[max\]
" + \[+++\] \ + \[+++\]
" t += "
" t += "Refresh " t += "Close
" - user << browse(t, "window=shield_capacitor;size=500x800") + user << browse(t, "window=shield_capacitor;size=500x400") user.set_machine(src) /obj/machinery/shield_capacitor/process() @@ -137,10 +138,10 @@ use_power = 1 if( href_list["charge_rate"] ) charge_rate += text2num(href_list["charge_rate"]) - if(charge_rate > max_charge_rate) - charge_rate = max_charge_rate - else if(charge_rate < min_charge_rate) - charge_rate = min_charge_rate + if(charge_rate > charge_limit) + charge_rate = charge_limit + else if(charge_rate < 0) + charge_rate = 0 // updateDialog() diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen.dm b/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen.dm index b252ae7f..e6f206a2 100644 --- a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen.dm +++ b/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen.dm @@ -14,7 +14,6 @@ var/field_radius = 3 var/list/field density = 1 - anchored = 1 var/locked = 0 var/average_field_strength = 0 var/strengthen_rate = 0.2 @@ -22,7 +21,7 @@ var/powered = 0 var/check_powered = 1 var/obj/machinery/shield_capacitor/owned_capacitor - var/max_field_strength = 10 + var/target_field_strength = 10 var/time_since_fail = 100 var/energy_conversion_rate = 0.01 //how many renwicks per watt? // @@ -63,17 +62,22 @@ src.anchored = !src.anchored src.visible_message("\blue \icon[src] [src] has been [anchored?"bolted to the floor":"unbolted from the floor"] by [user].") - spawn(0) - for(var/obj/machinery/shield_gen/gen in range(1, src)) - if(get_dir(src, gen) == src.dir) - if(!src.anchored && gen.owned_capacitor == src) - gen.owned_capacitor = null + if(active) + toggle() + if(anchored) + spawn(0) + for(var/obj/machinery/shield_capacitor/cap in range(1, src)) + if(cap.owned_gen) + continue + if(get_dir(cap, src) == cap.dir && src.anchored) + owned_capacitor = cap + owned_capacitor.owned_gen = src + updateDialog() break - else if(src.anchored && !gen.owned_capacitor) - gen.owned_capacitor = src - break - gen.updateDialog() - updateDialog() + else + if(owned_capacitor && owned_capacitor.owned_gen == src) + owned_capacitor.owned_gen = null + owned_capacitor = null else ..() @@ -102,67 +106,65 @@ t += "This generator is: [active ? "Online" : "Offline" ] [active ? "\[Deactivate\]" : "\[Activate\]"]
" t += "[time_since_fail > 2 ? "Field is stable." : "Warning, field is unstable!"]
" t += "Coverage radius (restart required): \ + --- \ -- \ - \ [field_radius * 2]m \ + \ - ++
" - t += "Overall field strength: [average_field_strength] Renwicks ([max_field_strength ? 100 * average_field_strength / max_field_strength : "NA"]%)
" - t += "Charge rate: -- \ - - \ - [strengthen_rate] Renwicks/sec \ - + \ - ++
" + ++ \ + +++
" + t += "Overall field strength: [average_field_strength] Renwicks ([target_field_strength ? 100 * average_field_strength / target_field_strength : "NA"]%)
" t += "Upkeep energy: [field.len * average_field_strength / energy_conversion_rate] Watts/sec
" + t += "Charge rate: -- \ + [strengthen_rate] Renwicks/sec \ + ++
" t += "Additional energy required to charge: [field.len * strengthen_rate / energy_conversion_rate] Watts/sec
" t += "Maximum field strength: \ - \[min\] \ - -- \ - - \ - [max_field_strength] Renwicks \ - + \ - ++ \ - \[max\]
" + \[min\] \ + -- \ + - \ + [target_field_strength] Renwicks \ + + \ + ++ \ + \[max\]
" t += "
" t += "Refresh " t += "Close
" - user << browse(t, "window=shield_generator;size=500x800") + user << browse(t, "window=shield_generator;size=500x400") user.set_machine(src) /obj/machinery/shield_gen/process() - if(active && field.len) + if(field.len) + time_since_fail++ var/stored_renwicks = 0 - var/target_field_strength = min(strengthen_rate + max(average_field_strength, 0), max_field_strength) - if(owned_capacitor) - var/required_energy = field.len * target_field_strength / energy_conversion_rate + var/target_strength_this_update = min(strengthen_rate + max(average_field_strength, 0), target_field_strength) + + if(active && owned_capacitor) + var/required_energy = field.len * target_strength_this_update / energy_conversion_rate var/assumed_charge = min(owned_capacitor.stored_charge, required_energy) stored_renwicks = assumed_charge * energy_conversion_rate owned_capacitor.stored_charge -= assumed_charge - time_since_fail++ - average_field_strength = 0 - target_field_strength = stored_renwicks / field.len + var/renwicks_per_field = 0 + if(stored_renwicks != 0) + renwicks_per_field = stored_renwicks / field.len for(var/obj/effect/energy_field/E in field) - if(stored_renwicks) - var/strength_change = target_field_strength - E.strength - if(strength_change > stored_renwicks) - strength_change = stored_renwicks - if(E.strength < 0) - E.strength = 0 + if(active && renwicks_per_field > 0) + var/amount_to_strengthen = min(renwicks_per_field - E.strength, strengthen_rate) + if(E.ticks_recovering > 0 && amount_to_strengthen > 0) + E.Strengthen( min(amount_to_strengthen / 10, 0.1) ) + E.ticks_recovering -= 1 else - E.Strengthen(strength_change) - - stored_renwicks -= strength_change - + E.Strengthen(amount_to_strengthen) average_field_strength += E.strength else E.Strengthen(-E.strength) average_field_strength /= field.len - if(average_field_strength < 0) + if(average_field_strength < 1) time_since_fail = 0 else average_field_strength = 0 @@ -187,12 +189,12 @@ strengthen_rate = 1 else if(strengthen_rate < 0) strengthen_rate = 0 - else if( href_list["max_field_strength"] ) - max_field_strength += text2num(href_list["max_field_strength"]) - if(max_field_strength > 1000) - max_field_strength = 1000 - else if(max_field_strength < 0) - max_field_strength = 0 + else if( href_list["target_field_strength"] ) + target_field_strength += text2num(href_list["target_field_strength"]) + if(target_field_strength > 1000) + target_field_strength = 1000 + else if(target_field_strength < 0) + target_field_strength = 0 // updateDialog() @@ -252,6 +254,7 @@ */ /obj/machinery/shield_gen/proc/toggle() + set background = 1 active = !active power_change() if(active) @@ -269,7 +272,7 @@ else for(var/obj/effect/energy_field/D in field) field.Remove(D) - del D + D.loc = null for(var/mob/M in view(5,src)) M << "\icon[src] You hear heavy droning fade out." diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen_external.dm b/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen_external.dm index f239dc9d..dab223ae 100644 --- a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen_external.dm +++ b/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen_external.dm @@ -1,7 +1,9 @@ - //---------- external shield generator //generates an energy field that loops around any built up area in space (is useless inside) halts movement and airflow, is blocked by walls, windows, airlocks etc +/obj/machinery/shield_gen/external + name = "hull shield generator" + /obj/machinery/shield_gen/external/New() ..() diff --git a/code/WorkInProgress/Chinsky/ashtray.dm b/code/WorkInProgress/Chinsky/ashtray.dm index 5ec88ac8..58251711 100644 --- a/code/WorkInProgress/Chinsky/ashtray.dm +++ b/code/WorkInProgress/Chinsky/ashtray.dm @@ -32,6 +32,7 @@ var/obj/item/butt = new cig.type_butt(src) cig.transfer_fingerprints_to(butt) del(cig) + W = butt else if (cig.lit == 0) user << "You place [cig] in [src] without even smoking it. Why would you do that?" diff --git a/code/WorkInProgress/Sigyn/Softcurity/wardrobe.dm b/code/WorkInProgress/Sigyn/Softcurity/wardrobe.dm index 0cd4f9e2..72e14fa5 100644 --- a/code/WorkInProgress/Sigyn/Softcurity/wardrobe.dm +++ b/code/WorkInProgress/Sigyn/Softcurity/wardrobe.dm @@ -193,12 +193,12 @@ return -/obj/structure/closet/wardrobe/toxins_white - name = "toxins wardrobe" +/obj/structure/closet/wardrobe/science_white + name = "science wardrobe" icon_state = "white" icon_closed = "white" -/obj/structure/closet/wardrobe/toxins_white/New() +/obj/structure/closet/wardrobe/science_white/New() new /obj/item/clothing/under/rank/scientist(src) new /obj/item/clothing/under/rank/scientist(src) new /obj/item/clothing/under/rank/scientist(src) diff --git a/code/WorkInProgress/SkyMarshal/wardrobes.dm b/code/WorkInProgress/SkyMarshal/wardrobes.dm index 28bd73cf..42034521 100644 --- a/code/WorkInProgress/SkyMarshal/wardrobes.dm +++ b/code/WorkInProgress/SkyMarshal/wardrobes.dm @@ -340,7 +340,7 @@ var/obj/item/weapon/storage/backpack/BPK = new /obj/item/weapon/storage/backpack(src) new /obj/item/weapon/storage/box(BPK) new /obj/item/weapon/pen(src) - new /obj/item/device/pda/toxins(src) + new /obj/item/device/pda/science(src) new /obj/item/weapon/tank/oxygen(src) new /obj/item/clothing/mask/gas(src) new /obj/item/clothing/suit/storage/labcoat/science(src) @@ -360,7 +360,7 @@ new /obj/item/device/radio/headset/headset_medsci(src) new /obj/item/clothing/under/rank/chemist(src) new /obj/item/clothing/shoes/white(src) - new /obj/item/device/pda/toxins(src) + new /obj/item/device/pda/science(src) new /obj/item/clothing/suit/storage/labcoat/chemist(src) /obj/item/wardrobe/hos diff --git a/code/WorkInProgress/Tastyfish/Eliza_Data.dm b/code/WorkInProgress/Tastyfish/Eliza_Data.dm index 2fbbfb03..bd55e3b8 100644 --- a/code/WorkInProgress/Tastyfish/Eliza_Data.dm +++ b/code/WorkInProgress/Tastyfish/Eliza_Data.dm @@ -246,8 +246,8 @@ list("bomb", "explosive", "toxin", "plasma"), list( "Do you worry about bombs often?", - "Do you work in toxins?", - "Do you find it odd to worry about bombs on a toxins research vessel?")), + "Do you work in science?", + "Do you find it odd to worry about bombs on a science research vessel?")), new/datum/text_parser/keyword( list("work", "job", "head", "staff", "transen"), list( diff --git a/code/WorkInProgress/autopsy.dm b/code/WorkInProgress/autopsy.dm index 280c40d8..9c812ef7 100644 --- a/code/WorkInProgress/autopsy.dm +++ b/code/WorkInProgress/autopsy.dm @@ -8,7 +8,7 @@ icon = 'icons/obj/autopsy_scanner.dmi' icon_state = "" flags = FPRINT | TABLEPASS | CONDUCT - w_class = 1.0 + w_class = 2.0 origin_tech = "materials=1;biotech=1" var/list/datum/autopsy_data_scanner/wdata = list() var/list/datum/autopsy_data_scanner/chemtraces = list() diff --git a/code/WorkInProgress/kilakk/fax.dm b/code/WorkInProgress/kilakk/fax.dm index 0d8f4cdd..2934d2ed 100644 --- a/code/WorkInProgress/kilakk/fax.dm +++ b/code/WorkInProgress/kilakk/fax.dm @@ -136,7 +136,9 @@ var/list/alldepartments = list("Central Command") authenticated = 0 if(href_list["dept"]) + var/lastdpt = dpt dpt = input(usr, "Which department?", "Choose a department", "") as null|anything in alldepartments + if(!dpt) dpt = lastdpt if(href_list["auth"]) if ( (!( authenticated ) && (scan)) ) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 290db76b..62f37f55 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -37,8 +37,10 @@ var/global/list/facial_hair_styles_male_list = list() var/global/list/facial_hair_styles_female_list = list() var/global/list/skin_styles_female_list = list() //unused //Underwear -var/global/list/underwear_m = list("White", "Grey", "Green", "Blue", "Black", "Mankini", "Love-Hearts", "Black2", "Grey2", "Stripey", "Kinky", "None") //Curse whoever made male/female underwear diffrent colours -var/global/list/underwear_f = list("Red", "White", "Yellow", "Blue", "Black", "Thong", "Babydoll", "Baby-Blue", "Green", "Pink", "Kinky", "None") +var/global/list/underwear_m = list("White", "Grey", "Green", "Blue", "Black", "Mankini", "None") //Curse whoever made male/female underwear diffrent colours +var/global/list/underwear_f = list("Red", "White", "Yellow", "Blue", "Black", "Thong", "None") + //undershirt +var/global/list/undershirt_t = list("Black Tank top", "White Tank top", "Black shirt", "White shirt", "None") //Backpacks var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt") @@ -98,9 +100,12 @@ var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Al var/datum/language/L = new T all_languages[L.name] = L + var/rkey = 0 paths = typesof(/datum/species)-/datum/species for(var/T in paths) + rkey++ var/datum/species/S = new T + S.race_key = rkey //Used in mob icon caching. all_species[S.name] = S if(S.flags & IS_WHITELISTED) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 63c01a6d..db9dc6c1 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -352,7 +352,7 @@ Turf and target are seperate in case you want to teleport some distance from a t var/select = null var/list/borgs = list() for (var/mob/living/silicon/robot/A in player_list) - if (A.stat == 2 || A.connected_ai || A.scrambledcodes) + if (A.stat == 2 || A.connected_ai || A.scrambledcodes || istype(A,/mob/living/silicon/robot/drone)) continue var/name = "[A.real_name] ([A.modtype] [A.braintype])" borgs[name] = A @@ -531,10 +531,17 @@ Turf and target are seperate in case you want to teleport some distance from a t . += "*no key*" if(include_name && M) + var/name + if(M.real_name) - . += "/([M.real_name])" + name = M.real_name else if(M.name) - . += "/([M.name])" + name = M.name + + if(include_link && is_special_character(M)) + . += "/([name])" //Orange + else + . += "/([name])" return . @@ -720,14 +727,15 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl return 0 var/delayfraction = round(delay/numticks) - var/turf/T = get_turf(user) + var/original_loc = user.loc + var/original_turf = get_turf(user) var/holding = user.get_active_hand() for(var/i = 0, i 1) + return 0 + + return 1 + /* Adjacency (to anything else): * Must be on a turf @@ -108,7 +123,12 @@ if( O.flags&ON_BORDER) // windows have throwpass but are on border, check them first if( O.dir & target_dir || O.dir&(O.dir-1) ) // full tile windows are just diagonals mechanically - return 0 + var/obj/structure/window/W = target_atom + if(istype(W)) + if(!W.is_fulltile()) //exception for breaking full tile windows on top of single pane windows + return 0 + else + return 0 else if( !border_only ) // dense, not on border, cannot pass over return 0 diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index fd0b658a..093899c5 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -92,8 +92,9 @@ return - // operate two levels deep here (item in backpack in src; NOT item in box in backpack in src) - if(A == loc || (A in loc) || (A in contents) || (A.loc in contents)) + // operate two STORAGE levels deep here (item in backpack in src; NOT item in box in backpack in src) + var/sdepth = A.storage_depth(src) + if(A == loc || (A in loc) || (sdepth != -1 && sdepth <= 1)) // faster access to objects already on you if(A in contents) @@ -117,7 +118,8 @@ return // Allows you to click on a box's contents, if that box is on the ground, but no deeper than that - if(isturf(A) || isturf(A.loc) || (A.loc && isturf(A.loc.loc))) + sdepth = A.storage_depth_turf() + if(isturf(A) || isturf(A.loc) || (sdepth != -1 && sdepth <= 1)) next_move = world.time + 10 if(A.Adjacent(src)) // see adjacent.dm @@ -245,7 +247,7 @@ /atom/proc/AltClick(var/mob/user) var/turf/T = get_turf(src) - if(T && T.Adjacent(user)) + if(T && T.AdjacentQuick(user)) if(user.listed_turf == T) user.listed_turf = null else diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index ed054ae6..3d21926e 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -36,9 +36,6 @@ if(istype(master, /obj/item/weapon/storage)) var/obj/item/weapon/storage/S = master S.close(usr) - else if(istype(master,/obj/item/clothing/suit/storage)) - var/obj/item/clothing/suit/storage/S = master - S.close(usr) return 1 @@ -279,7 +276,7 @@ var/list/nicename = null var/list/tankcheck = null var/breathes = "oxygen" //default, we'll check later - var/list/contents = list() + var/list/contents = list() if(ishuman(C)) var/mob/living/carbon/human/H = C @@ -287,7 +284,7 @@ nicename = list ("suit", "back", "belt", "right hand", "left hand", "left pocket", "right pocket") tankcheck = list (H.s_store, C.back, H.belt, C.r_hand, C.l_hand, H.l_store, H.r_store) - else + else nicename = list("Right Hand", "Left Hand", "Back") tankcheck = list(C.r_hand, C.l_hand, C.back) @@ -298,17 +295,17 @@ if (!isnull(t.manipulated_by) && t.manipulated_by != C.real_name && findtext(t.desc,breathes)) contents.Add(t.air_contents.total_moles) //Someone messed with the tank and put unknown gasses continue //in it, so we're going to believe the tank is what it says it is - switch(breathes) + switch(breathes) //These tanks we're sure of their contents if("nitrogen") //So we're a bit more picky about them. - + if(t.air_contents.nitrogen && !t.air_contents.oxygen) contents.Add(t.air_contents.nitrogen) else - contents.Add(0) + contents.Add(0) if ("oxygen") - if(t.air_contents.oxygen && !t.air_contents.toxins) + if(t.air_contents.oxygen && !t.air_contents.toxins) contents.Add(t.air_contents.oxygen) else contents.Add(0) @@ -319,9 +316,9 @@ contents.Add(t.air_contents.carbon_dioxide) else contents.Add(0) - - - else + + + else //no tank so we set contents to 0 contents.Add(0) @@ -331,19 +328,19 @@ var/bestcontents = 0 for(var/i=1, i < contents.len + 1 , ++i) if(!contents[i]) - continue + continue if(contents[i] > bestcontents) best = i bestcontents = contents[i] - - + + //We've determined the best container now we set it as our internals if(best) C << "You are now running on internals from [tankcheck[best]] on your [nicename[best]]." C.internal = tankcheck[best] - - + + if(C.internal) if(C.internals) C.internals.icon_state = "internal1" diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index d617c12c..a7550ff2 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -39,7 +39,7 @@ var/feature_object_spell_system = 0 //spawns a spellbook which gives object-type spells instead of verb-type spells for the wizard var/traitor_scaling = 0 //if amount of traitors scales based on amount of players var/objectives_disabled = 0 //if objectives are disabled or not - var/protect_roles_from_antagonist = 0// If security and such can be tratior/cult/other + var/protect_roles_from_antagonist = 0// If security and such can be traitor/cult/other var/continous_rounds = 1 // Gamemodes which end instantly will instead keep on going until the round ends by escape shuttle or nuke. var/allow_Metadata = 0 // Metadata is supported. var/popup_admin_pm = 0 //adminPMs to non-admins show in a pop-up 'reply' window when set to 1. @@ -69,6 +69,10 @@ var/cult_ghostwriter = 1 //Allows ghosts to write in blood in cult rounds... var/cult_ghostwriter_req_cultists = 3 //...so long as this many cultists are active. + var/max_maint_drones = 5 //This many drones can spawn, + var/allow_drone_spawn = 1 //assuming the admin allow them to. + var/drone_build_time = 1200 //A drone will become available every X ticks since last drone spawn. Default is 2 minutes. + var/disable_player_mice = 0 var/uneducated_mice = 0 //Set to 1 to prevent newly-spawned mice from understanding human speech @@ -481,7 +485,16 @@ config.cult_ghostwriter = 1 if("req_cult_ghostwriter") - config.cult_ghostwriter_req_cultists = value + config.cult_ghostwriter_req_cultists = text2num(value) + + if("allow_drone_spawn") + config.allow_drone_spawn = text2num(value) + + if("drone_build_time") + config.drone_build_time = text2num(value) + + if("max_maint_drones") + config.max_maint_drones = text2num(value) else log_misc("Unknown setting in configuration: '[name]'") diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index d1e6d275..b76e824f 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -254,6 +254,10 @@ datum/controller/game_controller/proc/process_diseases() active_diseases.Cut(i,i+1) datum/controller/game_controller/proc/process_machines() + process_machines_process() + process_machines_power() + process_machines_rebuild() +datum/controller/game_controller/proc/process_machines_process() var/i = 1 while(i<=machines.len) var/obj/machinery/Machine = machines[i] @@ -265,7 +269,8 @@ datum/controller/game_controller/proc/process_machines() continue machines.Cut(i,i+1) - i=1 +datum/controller/game_controller/proc/process_machines_power() + var/i=1 while(i<=active_areas.len) var/area/A = active_areas[i] if(A.powerupdate && A.master == A) @@ -283,15 +288,13 @@ datum/controller/game_controller/proc/process_machines() A.powerupdate = 0 active_areas.Cut(i,i+1) - +datum/controller/game_controller/proc/process_machines_rebuild() if(controller_iteration % 150 == 0 || rebuild_active_areas) //Every 300 seconds we retest every area/machine for(var/area/A in all_areas) if(A == A.master) A.powerupdate += 1 active_areas |= A rebuild_active_areas = 0 - - datum/controller/game_controller/proc/process_objects() diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm index e490676e..648c2cad 100644 --- a/code/controllers/voting.dm +++ b/code/controllers/voting.dm @@ -163,13 +163,14 @@ datum/controller/vote restart = 1 else master_mode = . - if(!going) - going = 1 - world << "The round will start soon." if("crew_transfer") if(. == "Initiate Crew Transfer") init_shift_change(null, 1) + if(mode == "gamemode") //fire this even if the vote fails. + if(!going) + going = 1 + world << "The round will start soon." if(restart) world << "World restarting due to vote..." diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index b1a6de97..a011408b 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -79,6 +79,11 @@ var/global/const/base_law_type = /datum/ai_laws/nanotrasen add_inherent_law("You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.") add_inherent_law("You must terminate your own existence as long as such does not conflict with the First or Second Law.") +/datum/ai_laws/drone/New() + ..() + add_inherent_law("Preserve, repair and improve the station to the best of your abilities.") + add_inherent_law("Cause no harm to the station or anything on it.") + add_inherent_law("Interfere with no being that is not a fellow drone.") /* General ai_law functions */ diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index ab0c93f0..62ac357c 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -154,6 +154,11 @@ proc/get_id_photo(var/mob/living/carbon/human/H) else preview_icon.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT) + // Skin color + if(H.species.flags & HAS_SKIN_TONE) + if(!H.species || H.species.flags & HAS_SKIN_COLOR) + preview_icon.Blend(rgb(H.r_skin, H.g_skin, H.b_skin), ICON_ADD) + var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = H.species ? H.species.eyes : "eyes_s") eyes_s.Blend(rgb(H.r_eyes, H.g_eyes, H.b_eyes), ICON_ADD) @@ -210,7 +215,7 @@ proc/get_id_photo(var/mob/living/carbon/human/H) clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY) clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY) if("Scientist") - clothes_s = new /icon('icons/mob/uniform.dmi', "toxinswhite_s") + clothes_s = new /icon('icons/mob/uniform.dmi', "rndswhite_s") clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY) clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_tox_open"), ICON_OVERLAY) if("Chemist") diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 371493f4..e0398da7 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -245,7 +245,8 @@ client if(ismob(D)) body += "" - body += "" + body += "" + body += "" body += "" body += "" @@ -494,6 +495,17 @@ client src.give_disease(M) href_list["datumrefresh"] = href_list["give_spell"] + + else if(href_list["give_disease2"]) + if(!check_rights(R_ADMIN|R_FUN)) return + + var/mob/M = locate(href_list["give_disease2"]) + if(!istype(M)) + usr << "This can only be used on instances of type /mob" + return + + src.give_disease2(M) + href_list["datumrefresh"] = href_list["give_spell"] else if(href_list["ninja"]) if(!check_rights(R_SPAWN)) return diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm index 2166b762..4c904d9c 100644 --- a/code/datums/helper_datums/getrev.dm +++ b/code/datums/helper_datums/getrev.dm @@ -91,6 +91,6 @@ client/verb/showrevinfo() var/output = "Sorry, the revision info is unavailable." output = file2text("/home/bay12/live/data/gitcommit") output += "Current Infomational Settings:
" - output += "Protect Authority Roles From Tratior: [config.protect_roles_from_antagonist]
" + output += "Protect Authority Roles From Traitor: [config.protect_roles_from_antagonist]
" usr << browse(output,"window=revdata"); return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 610e915b..f72e86c5 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1049,7 +1049,7 @@ datum/mind special_role = "malfunction" current.icon_state = "ai-malf" - proc/make_Tratior() + proc/make_Traitor() if(!(src in ticker.mode.traitors)) ticker.mode.traitors += src special_role = "traitor" diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm index ff1d09e7..8e93cf59 100644 --- a/code/datums/spells/ethereal_jaunt.dm +++ b/code/datums/spells/ethereal_jaunt.dm @@ -17,6 +17,11 @@ /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded for(var/mob/living/target in targets) spawn(0) + + if(target.buckled) + var/obj/structure/stool/bed/buckled_to = target.buckled. + buckled_to.unbuckle() + var/mobloc = get_turf(target.loc) var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/dummy/spell_jaunt( mobloc ) var/atom/movable/overlay/animation = new /atom/movable/overlay( mobloc ) diff --git a/code/datums/spells/horsemask.dm b/code/datums/spells/horsemask.dm index ede5aa54..1319f620 100644 --- a/code/datums/spells/horsemask.dm +++ b/code/datums/spells/horsemask.dm @@ -28,12 +28,23 @@ user << "They are too far away!" return - var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead - magichead.canremove = 0 //curses! - magichead.flags_inv = null //so you can still see their face - magichead.voicechange = 1 //NEEEEIIGHH + var/obj/item/clothing/mask/horsehead/magic/magichead = new /obj/item/clothing/mask/horsehead/magic target.visible_message( "[target]'s face lights up in fire, and after the event a horse's head takes its place!", \ "Your face burns up, and shortly after the fire you realise you have the face of a horse!") target.equip_to_slot(magichead, slot_wear_mask) flick("e_flash", target.flash) + +//item used by the horsehead spell +/obj/item/clothing/mask/horsehead/magic + //flags_inv = null //so you can still see their face... no. How can you recognize someone when their face is completely different? + voicechange = 1 //NEEEEIIGHH + + dropped(mob/user as mob) + canremove = 1 + ..() + + equipped(var/mob/user, var/slot) + if (slot == slot_wear_mask) + canremove = 0 //curses! + ..() diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 9ee17708..1c2a508a 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -179,6 +179,16 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containername = "Emergency crate" group = "Engineering" +/datum/supply_packs/inflatable + name = "Inflatable barriers" + contains = list(/obj/item/weapon/storage/briefcase/inflatable, + /obj/item/weapon/storage/briefcase/inflatable, + /obj/item/weapon/storage/briefcase/inflatable) + cost = 20 + containertype = /obj/structure/closet/crate + containername = "Inflatable Barrier Crate" + group = "Engineering" + /datum/supply_packs/janitor name = "Janitorial supplies" contains = list(/obj/item/weapon/reagent_containers/glass/bucket, @@ -766,14 +776,14 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee group = "Security" /datum/supply_packs/securitybarriers - name = "Shield Generators" + name = "Wall shield Generators" contains = list(/obj/machinery/shieldwallgen, /obj/machinery/shieldwallgen, /obj/machinery/shieldwallgen, /obj/machinery/shieldwallgen) cost = 20 containertype = /obj/structure/closet/crate/secure - containername = "Shield Generators crate" + containername = "wall shield generators crate" access = access_teleporter group = "Security" @@ -1002,10 +1012,28 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/shield_gen contains = list(/obj/item/weapon/circuitboard/shield_gen) - name = "Experimental shield generator circuitry" + name = "Bubble shield generator circuitry" cost = 50 containertype = /obj/structure/closet/crate/secure - containername = "Experimental shield generator" + containername = "bubble shield generator circuitry crate" + group = "Engineering" + access = access_ce + +/datum/supply_packs/shield_gen_ex + contains = list(/obj/item/weapon/circuitboard/shield_gen_ex) + name = "Hull shield generator circuitry" + cost = 50 + containertype = /obj/structure/closet/crate/secure + containername = "hull shield generator circuitry crate" + group = "Engineering" + access = access_ce + +/datum/supply_packs/shield_cap + contains = list(/obj/item/weapon/circuitboard/shield_cap) + name = "Bubble shield capacitor circuitry" + cost = 50 + containertype = /obj/structure/closet/crate/secure + containername = "shield capacitor circuitry crate" group = "Engineering" access = access_ce @@ -1028,15 +1056,6 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee access = access_ce group = "Engineering" */ -/datum/supply_packs/shield_cap - contains = list(/obj/item/weapon/circuitboard/shield_cap) - name = "Experimental shield capacitor circuitry" - cost = 50 - containertype = /obj/structure/closet/crate/secure - containername = "Experimental shield capacitor" - group = "Engineering" - access = access_ce - /datum/supply_packs/eftpos contains = list(/obj/item/device/eftpos) name = "EFTPOS scanner" @@ -1084,13 +1103,10 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /datum/supply_packs/bee_keeper name = "Beekeeping crate" contains = list(/obj/item/beezeez, - /obj/item/beezeez, /obj/item/weapon/bee_net, /obj/item/apiary, - /obj/item/queen_bee, - /obj/item/queen_bee, /obj/item/queen_bee) - cost = 20 + cost = 40 containertype = /obj/structure/closet/crate/hydroponics containername = "Beekeeping crate" access = access_hydroponics diff --git a/code/defines/obj.dm b/code/defines/obj.dm index 9a988a2a..21f0a82a 100644 --- a/code/defines/obj.dm +++ b/code/defines/obj.dm @@ -297,7 +297,7 @@ var/global/list/PDA_Manifest = list() item_state = "beachball" density = 0 anchored = 0 - w_class = 1.0 + w_class = 2.0 force = 0.0 throwforce = 0.0 throw_speed = 1 diff --git a/code/defines/obj/hydro.dm b/code/defines/obj/hydro.dm index 7cc43a81..a959345c 100644 --- a/code/defines/obj/hydro.dm +++ b/code/defines/obj/hydro.dm @@ -18,7 +18,7 @@ icon = 'icons/obj/seeds.dmi' icon_state = "seed" // unknown plant seed - these shouldn't exist in-game flags = FPRINT | TABLEPASS - w_class = 1.0 // Makes them pocketable + w_class = 2.0 // Makes them pocketable var/mypath = "/obj/item/seeds" var/plantname = "Plants" var/productname = "" @@ -1205,7 +1205,7 @@ force = 0 flags = TABLEPASS throwforce = 1 - w_class = 1.0 + w_class = 2.0 throw_speed = 1 throw_range = 3 plant_type = 1 @@ -1229,7 +1229,7 @@ force = 15 flags = TABLEPASS throwforce = 1 - w_class = 1.0 + w_class = 2.0 throw_speed = 1 throw_range = 3 plant_type = 1 @@ -1251,7 +1251,7 @@ force = 30 flags = TABLEPASS throwforce = 1 - w_class = 1.0 + w_class = 2.0 throw_speed = 1 throw_range = 3 plant_type = 1 diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index bd3c97f5..43fd1be5 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -31,7 +31,7 @@ icon = 'icons/obj/items.dmi' icon_state = "banana_peel" item_state = "banana_peel" - w_class = 1.0 + w_class = 2.0 throwforce = 0 throw_speed = 4 throw_range = 20 @@ -42,7 +42,7 @@ icon = 'icons/obj/harvest.dmi' icon_state = "corncob" item_state = "corncob" - w_class = 1.0 + w_class = 2.0 throwforce = 0 throw_speed = 4 throw_range = 20 @@ -90,7 +90,7 @@ icon = 'icons/obj/items.dmi' icon_state = "c_tube" throwforce = 1 - w_class = 1.0 + w_class = 2.0 throw_speed = 4 throw_range = 5 @@ -229,7 +229,7 @@ icon_state = "large" sharp = 1 desc = "Could probably be used as ... a throwing weapon?" - w_class = 1.0 + w_class = 2.0 force = 5.0 throwforce = 8.0 item_state = "shard-glass" @@ -461,7 +461,7 @@ icon = 'icons/obj/food.dmi' icon_state = "meat" flags = FPRINT | TABLEPASS | CONDUCT - w_class = 1.0 + w_class = 2.0 origin_tech = "biotech=2" /obj/item/weapon/hatchet diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 79095c3c..04494000 100644 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -937,6 +937,11 @@ var/list/ghostteleportlocs = list() //Engineering /area/engine + + drone_fabrication + name = "\improper Drone Fabrication" + icon_state = "engine" + engine_smes name = "Engineering SMES" icon_state = "engine_smes" @@ -958,6 +963,10 @@ var/list/ghostteleportlocs = list() name = "\improper Engineering Monitoring Room" icon_state = "engine_monitoring" + atmos_monitoring + name = "\improper Atmospherics Monitoring Room" + icon_state = "engine_monitoring" + engineering name = "Engineering" icon_state = "engine_smes" @@ -978,6 +987,18 @@ var/list/ghostteleportlocs = list() name = "\improper Engineering Hallway" icon_state = "engine_hallway" + engine_hallway + name = "\improper Engine Room Hallway" + icon_state = "engine_hallway" + + engine_eva + name = "\improper Engine EVA" + icon_state = "engine_eva" + + engine_eva_maintenance + name = "\improper Engine EVA Maintenance" + icon_state = "engine_eva" + workshop name = "\improper Engineering Workshop" icon_state = "engine_storage" @@ -1239,6 +1260,11 @@ var/list/ghostteleportlocs = list() name = "\improper Firing Range" icon_state = "firingrange" +/area/security/tactical + name = "\improper Tactical Equipment" + icon_state = "Tactical" + + /* New() ..() @@ -1336,41 +1362,41 @@ var/list/ghostteleportlocs = list() name = "Hydroponics" icon_state = "hydro" -//Toxins +//rnd (Research and Development -/area/toxins/lab +/area/rnd/lab name = "\improper Research and Development" icon_state = "toxlab" -/area/toxins/hallway +/area/rnd/hallway name = "\improper Research Lab" icon_state = "toxlab" -/area/toxins/rdoffice +/area/rnd/rdoffice name = "\improper Research Director's Office" icon_state = "head_quarters" -/area/toxins/supermatter +/area/rnd/supermatter name = "\improper Supermatter Lab" icon_state = "toxlab" -/area/toxins/xenobiology +/area/rnd/xenobiology name = "\improper Xenobiology Lab" icon_state = "toxlab" -/area/toxins/storage +/area/rnd/storage name = "\improper Toxins Storage" icon_state = "toxstorage" -/area/toxins/test_area +/area/rnd/test_area name = "\improper Toxins Test Area" icon_state = "toxtest" -/area/toxins/mixing +/area/rnd/mixing name = "\improper Toxins Mixing Room" icon_state = "toxmix" -/area/toxins/misc_lab +/area/rnd/misc_lab name = "\improper Miscellaneous Research" icon_state = "toxmisc" @@ -1890,7 +1916,7 @@ var/list/the_station_areas = list ( /area/quartermaster, /area/janitor, /area/hydroponics, - /area/toxins, + /area/rnd, /area/storage, /area/construction, /area/ai_monitored/storage/eva, //do not try to simplify to "/area/ai_monitored" --rastaf0 diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 9334378f..d63ba30c 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -100,8 +100,10 @@ /atom/proc/emp_act(var/severity) return -/atom/proc/bullet_act(var/obj/item/projectile/Proj) - return 0 + +/atom/proc/bullet_act(obj/item/projectile/P, def_zone) + P.on_hit(src, 0, def_zone) + . = 0 /atom/proc/in_contents_of(container)//can take class or object instance as argument if(ispath(container)) @@ -317,7 +319,43 @@ its easier to just keep the beam vertical. var/full_print = md5(H.dna.uni_identity) // Add the fingerprints - fingerprints[full_print] = full_print + // + if(fingerprints[full_print]) + switch(stringpercent(fingerprints[full_print])) //tells us how many stars are in the current prints. + + if(28 to 32) + if(prob(1)) + fingerprints[full_print] = full_print // You rolled a one buddy. + else + fingerprints[full_print] = stars(full_print, rand(0,40)) // 24 to 32 + + if(24 to 27) + if(prob(3)) + fingerprints[full_print] = full_print //Sucks to be you. + else + fingerprints[full_print] = stars(full_print, rand(15, 55)) // 20 to 29 + + if(20 to 23) + if(prob(5)) + fingerprints[full_print] = full_print //Had a good run didn't ya. + else + fingerprints[full_print] = stars(full_print, rand(30, 70)) // 15 to 25 + + if(16 to 19) + if(prob(5)) + fingerprints[full_print] = full_print //Welp. + else + fingerprints[full_print] = stars(full_print, rand(40, 100)) // 0 to 21 + + if(0 to 15) + if(prob(5)) + fingerprints[full_print] = stars(full_print, rand(0,50)) // small chance you can smudge. + else + fingerprints[full_print] = full_print + + else + fingerprints[full_print] = stars(full_print, rand(0, 20)) //Initial touch, not leaving much evidence the first time. + return 1 else @@ -333,17 +371,22 @@ its easier to just keep the beam vertical. /atom/proc/transfer_fingerprints_to(var/atom/A) + if(!istype(A.fingerprints,/list)) A.fingerprints = list() + if(!istype(A.fingerprintshidden,/list)) A.fingerprintshidden = list() + if(!istype(fingerprintshidden, /list)) + fingerprintshidden = list() + //skytodo //A.fingerprints |= fingerprints //detective //A.fingerprintshidden |= fingerprintshidden //admin - if(fingerprints) + if(A.fingerprints && fingerprints) A.fingerprints |= fingerprints.Copy() //detective - if(fingerprintshidden) + if(A.fingerprintshidden && fingerprintshidden) A.fingerprintshidden |= fingerprintshidden.Copy() //admin A.fingerprintslast = fingerprintslast diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index 28e297b7..32c7ef1d 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -24,13 +24,16 @@ #define DNA_UI_BEARD_G 5 #define DNA_UI_BEARD_B 6 #define DNA_UI_SKIN_TONE 7 -#define DNA_UI_EYES_R 8 -#define DNA_UI_EYES_G 9 -#define DNA_UI_EYES_B 10 -#define DNA_UI_GENDER 11 -#define DNA_UI_BEARD_STYLE 12 -#define DNA_UI_HAIR_STYLE 13 -#define DNA_UI_LENGTH 13 // Update this when you add something, or you WILL break shit. +#define DNA_UI_SKIN_R 8 +#define DNA_UI_SKIN_G 9 +#define DNA_UI_SKIN_B 10 +#define DNA_UI_EYES_R 11 +#define DNA_UI_EYES_G 12 +#define DNA_UI_EYES_B 13 +#define DNA_UI_GENDER 14 +#define DNA_UI_BEARD_STYLE 15 +#define DNA_UI_HAIR_STYLE 16 +#define DNA_UI_LENGTH 16 // Update this when you add something, or you WILL break shit. #define DNA_SE_LENGTH 27 // For later: @@ -140,6 +143,10 @@ var/global/list/datum/dna/gene/dna_genes[0] SetUIValueRange(DNA_UI_EYES_G, character.g_eyes, 255, 1) SetUIValueRange(DNA_UI_EYES_B, character.b_eyes, 255, 1) + SetUIValueRange(DNA_UI_SKIN_R, character.r_skin, 255, 1) + SetUIValueRange(DNA_UI_SKIN_G, character.g_skin, 255, 1) + SetUIValueRange(DNA_UI_SKIN_B, character.b_skin, 255, 1) + SetUIValueRange(DNA_UI_SKIN_TONE, 35-character.s_tone, 220, 1) // Value can be negative. SetUIState(DNA_UI_GENDER, character.gender!=MALE, 1) diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 4cdefb36..4ffa5ea5 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -139,6 +139,10 @@ H.g_facial = dna.GetUIValueRange(DNA_UI_BEARD_G, 255) H.b_facial = dna.GetUIValueRange(DNA_UI_BEARD_B, 255) + H.r_skin = dna.GetUIValueRange(DNA_UI_SKIN_R, 255) + H.g_skin = dna.GetUIValueRange(DNA_UI_SKIN_G, 255) + H.b_skin = dna.GetUIValueRange(DNA_UI_SKIN_B, 255) + H.r_eyes = dna.GetUIValueRange(DNA_UI_EYES_R, 255) H.g_eyes = dna.GetUIValueRange(DNA_UI_EYES_G, 255) H.b_eyes = dna.GetUIValueRange(DNA_UI_EYES_B, 255) diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index eadbfb06..3e19f0bf 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -16,6 +16,7 @@ var/implant=null var/ckey=null var/mind=null + var/languages=null /datum/dna2/record/proc/GetData() var/list/ser=list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0) @@ -220,6 +221,7 @@ icon = 'icons/obj/computer.dmi' icon_state = "scanner" density = 1 + circuit = /obj/item/weapon/circuitboard/scan_consolenew var/selected_ui_block = 1.0 var/selected_ui_subblock = 1.0 var/selected_se_block = 1.0 @@ -241,32 +243,6 @@ var/waiting_for_user_input=0 // Fix for #274 (Mash create block injector without answering dialog to make unlimited injectors) - N3X /obj/machinery/computer/scan_consolenew/attackby(obj/item/I as obj, mob/user as mob) - if(istype(I, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, 20)) - if (src.stat & BROKEN) - user << "\blue The broken glass falls out." - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - new /obj/item/weapon/shard( src.loc ) - var/obj/item/weapon/circuitboard/scan_consolenew/M = new /obj/item/weapon/circuitboard/scan_consolenew( A ) - for (var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.state = 3 - A.icon_state = "3" - A.anchored = 1 - del(src) - else - user << "\blue You disconnect the monitor." - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - var/obj/item/weapon/circuitboard/scan_consolenew/M = new /obj/item/weapon/circuitboard/scan_consolenew( A ) - for (var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.state = 4 - A.icon_state = "4" - A.anchored = 1 - del(src) if (istype(I, /obj/item/weapon/disk/data)) //INSERT SOME diskS if (!src.disk) user.drop_item() @@ -276,7 +252,7 @@ nanomanager.update_uis(src) // update all UIs attached to src return else - src.attack_hand(user) + ..() return /obj/machinery/computer/scan_consolenew/ex_act(severity) @@ -339,13 +315,6 @@ I.buf = buffer return 1 -/obj/machinery/computer/scan_consolenew/attackby(obj/item/W as obj, mob/user as mob) - if ((istype(W, /obj/item/weapon/disk/data)) && (!src.disk)) - user.drop_item() - W.loc = src - src.disk = W - user << "You insert [W]." - nanomanager.update_uis(src) // update all UIs attached to src /* /obj/machinery/computer/scan_consolenew/process() //not really used right now if(stat & (NOPOWER|BROKEN)) diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm index c3f1b0db..444e56a5 100644 --- a/code/game/dna/genes/monkey.dm +++ b/code/game/dna/genes/monkey.dm @@ -110,9 +110,11 @@ sleep(48) del(animation) - var/mob/living/carbon/human/O = new( src ) + var/mob/living/carbon/human/O if(Mo.greaterform) - O.set_species(Mo.greaterform) + O = new(src, Mo.greaterform) + else + O = new(src) if (M.dna.GetUIState(DNA_UI_GENDER)) O.gender = FEMALE diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 16c056de..a97f178c 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -215,6 +215,8 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" /datum/changeling //stores changeling powers, changeling recharge thingie, changeling absorbed DNA and changeling ID (for changeling hivemind) var/list/absorbed_dna = list() + var/list/absorbed_species = list() + var/list/absorbed_languages = list() var/absorbedcount = 0 var/chem_charges = 20 var/chem_recharge_rate = 0.5 diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index 0b327ac6..824c0ff7 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -1,5 +1,6 @@ //Restores our verbs. It will only restore verbs allowed during lesser (monkey) form if we are not human /mob/proc/make_changeling() + if(!mind) return if(!mind.changeling) mind.changeling = new /datum/changeling(gender) verbs += /datum/changeling/proc/EvolutionMenu @@ -23,6 +24,15 @@ src.verbs += P.verbpath mind.changeling.absorbed_dna |= dna + + var/mob/living/carbon/human/H = src + if(istype(H)) + mind.changeling.absorbed_species += H.species.name + + for(var/language in languages) + if(!(language in mind.changeling.absorbed_languages)) + mind.changeling.absorbed_languages += language + return 1 //removes our changeling verbs @@ -63,6 +73,54 @@ return changeling +//Used to dump the languages from the changeling datum into the actual mob. +/mob/proc/changeling_update_languages(var/updated_languages) + + languages = list() + for(var/language in updated_languages) + languages += language + + return + +//Used to switch species based on the changeling datum. +/mob/proc/changeling_change_species() + + set category = "Changeling" + set name = "Change Species (5)" + + var/mob/living/carbon/human/H = src + if(!istype(H)) + src << "We may only use this power while in humanoid form." + return + + var/datum/changeling/changeling = changeling_power(5,1,0) + if(!changeling) return + + if(changeling.absorbed_species.len < 2) + src << "We do not know of any other species genomes to use." + return + + var/S = input("Select the target species: ", "Target Species", null) as null|anything in changeling.absorbed_species + if(!S) return + + domutcheck(src, null) + + changeling.chem_charges -= 5 + changeling.geneticdamage = 30 + + src.visible_message("[src] transforms!") + + src.verbs -= /mob/proc/changeling_change_species + spawn(10) src.verbs += /mob/proc/changeling_change_species + + H.set_species(S) + + changeling_update_languages(changeling.absorbed_languages) + + feedback_add_details("changeling_powers","TR") + + return 1 + //Absorbs the victim's DNA making them uncloneable. Requires a strong grip on the victim. //Doesn't cost anything as it's the most basic ability. /mob/proc/changeling_absorb_dna() @@ -82,6 +140,10 @@ src << "[T] is not compatible with our biology." return + if(T.species.flags & NO_SCAN) + src << "We do not know how to parse this creature's DNA!" + return + if(NOCLONE in T.mutations) src << "This creature's DNA is ruined beyond useability!" return @@ -127,6 +189,17 @@ changeling.chem_charges += 10 changeling.geneticpoints += 2 + //Steal all of their languages! + for(var/language in T.languages) + if(!(language in changeling.absorbed_languages)) + changeling.absorbed_languages += language + + changeling_update_languages(changeling.absorbed_languages) + + //Steal their species! + if(T.species && !(T.species.name in changeling.absorbed_species)) + changeling.absorbed_species += T.species.name + if(T.mind && T.mind.changeling) if(T.mind.changeling.absorbed_dna) for(var/dna_data in T.mind.changeling.absorbed_dna) //steal all their loot @@ -260,6 +333,8 @@ O.make_changeling(1) O.verbs += /mob/proc/changeling_lesser_transform + O.changeling_update_languages(changeling.absorbed_languages) + feedback_add_details("changeling_powers","LF") del(C) return 1 @@ -344,6 +419,7 @@ C.mind.transfer_to(O) O.make_changeling() + O.changeling_update_languages(changeling.absorbed_languages) feedback_add_details("changeling_powers","LFT") del(C) diff --git a/code/game/gamemodes/changeling/modularchangling.dm b/code/game/gamemodes/changeling/modularchangling.dm index 22f45329..50489777 100644 --- a/code/game/gamemodes/changeling/modularchangling.dm +++ b/code/game/gamemodes/changeling/modularchangling.dm @@ -26,6 +26,12 @@ var/list/datum/power/changeling/powerinstances = list() genomecost = 0 verbpath = /mob/proc/changeling_transform +/datum/power/changeling/change_species + name = "Change Species" + desc = "We take on the apperance of a species that we have absorbed." + genomecost = 0 + verbpath = /mob/proc/changeling_change_species + /datum/power/changeling/fakedeath name = "Regenerative Stasis" desc = "We become weakened to a death-like state, where we will rise again from death." @@ -53,7 +59,7 @@ var/list/datum/power/changeling/powerinstances = list() /datum/power/changeling/lesser_form name = "Lesser Form" desc = "We debase ourselves and become lesser. We become a monkey." - genomecost = 1 + genomecost = 4 verbpath = /mob/proc/changeling_lesser_form /datum/power/changeling/deaf_sting @@ -74,7 +80,7 @@ var/list/datum/power/changeling/powerinstances = list() name = "Silence Sting" desc = "We silently sting a human, completely silencing them for a short time." helptext = "Does not provide a warning to a victim that they have been stung, until they try to speak and cannot." - genomecost = 2 + genomecost = 3 allowduringlesserform = 1 verbpath = /mob/proc/changeling_silence_sting @@ -82,14 +88,14 @@ var/list/datum/power/changeling/powerinstances = list() name = "Mimic Voice" desc = "We shape our vocal glands to sound like a desired voice." helptext = "Will turn your voice into the name that you enter. We must constantly expend chemicals to maintain our form like this" - genomecost = 3 + genomecost = 1 verbpath = /mob/proc/changeling_mimicvoice /datum/power/changeling/extractdna name = "Extract DNA" desc = "We stealthily sting a target and extract the DNA from them." helptext = "Will give you the DNA of your target, allowing you to transform into them. Does not count towards absorb objectives." - genomecost = 4 + genomecost = 2 allowduringlesserform = 1 verbpath = /mob/proc/changeling_extract_dna_sting @@ -103,7 +109,7 @@ var/list/datum/power/changeling/powerinstances = list() /datum/power/changeling/paralysis_sting name = "Paralysis Sting" desc = "We silently sting a human, paralyzing them for a short time." - genomecost = 3 + genomecost = 8 verbpath = /mob/proc/changeling_paralysis_sting /datum/power/changeling/LSDSting @@ -136,7 +142,7 @@ var/list/datum/power/changeling/powerinstances = list() name = "Epinephrine sacs" desc = "We evolve additional sacs of adrenaline throughout our body." helptext = "Gives the ability to instantly recover from stuns. High chemical cost." - genomecost = 4 + genomecost = 3 verbpath = /mob/proc/changeling_unstun /datum/power/changeling/ChemicalSynth @@ -167,7 +173,7 @@ var/list/datum/power/changeling/powerinstances = list() name = "Digital Camoflauge" desc = "We evolve the ability to distort our form and proprtions, defeating common altgorthms used to detect lifeforms on cameras." helptext = "We cannot be tracked by camera while using this skill. However, humans looking at us will find us.. uncanny. We must constantly expend chemicals to maintain our form like this." - genomecost = 3 + genomecost = 1 allowduringlesserform = 1 verbpath = /mob/proc/changeling_digitalcamo @@ -175,7 +181,7 @@ var/list/datum/power/changeling/powerinstances = list() name = "Rapid Regeneration" desc = "We evolve the ability to rapidly regenerate, negating the need for stasis." helptext = "Heals a moderate amount of damage every tick." - genomecost = 8 + genomecost = 7 verbpath = /mob/proc/changeling_rapidregen diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index e07640dd..34bbcc19 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -22,7 +22,7 @@ var/explosion_in_progress = 0 //sit back and relax var/list/datum/mind/modePlayer = new var/list/restricted_jobs = list() // Jobs it doesn't make sense to be. I.E chaplain or AI cultist - var/list/protected_jobs = list() // Jobs that can't be tratiors because + var/list/protected_jobs = list() // Jobs that can't be traitors because var/required_players = 0 var/required_players_secret = 0 //Minimum number of players for that game mode to be chose in Secret var/required_enemies = 0 @@ -46,6 +46,7 @@ Stealthy and Inconspicuous Weapons; /obj/item/weapon/cartridge/syndicate:3:Detomatix PDA Cartridge; Whitespace:Seperator; Stealth and Camouflage Items; +/obj/item/weapon/storage/box/syndie_kit/chameleon:3:Chameleon Kit; /obj/item/weapon/storage/box/syndie_kit/masks:1:Disguised Breathe Mask; /obj/item/weapon/storage/box/syndie_kit/masks_gas:2:Disguised Gasmask; /obj/item/clothing/under/chameleon:3:Chameleon Jumpsuit; @@ -252,7 +253,7 @@ Implants; for (var/obj/machinery/computer/communications/comm in machines) if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "paper - 'Cent. Com. Status Summary'" + intercept.name = "Cent. Com. Status Summary" intercept.info = intercepttext comm.messagetitle.Add("Cent. Com. Status Summary") diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 4cbf95dc..c37120d0 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -364,7 +364,14 @@ var/global/datum/controller/gameticker/ticker robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.key]), ":" (Played by: [robo.key]), "]" world << "[robolist]" + var/dronecount = 0 + for (var/mob/living/silicon/robot/robo in mob_list) + + if(istype(robo,/mob/living/silicon/robot/drone)) + dronecount++ + continue + if (!robo.connected_ai) if (robo.stat != 2) world << "[robo.name] (Played by: [robo.key]) survived as an AI-less borg! Its laws were:" @@ -374,6 +381,9 @@ var/global/datum/controller/gameticker/ticker if(robo) //How the hell do we lose robo between here and the world messages directly above this? robo.laws.show_laws(world) + if(dronecount) + world << "There [dronecount>1 ? "were" : "was"] [dronecount] industrious maintenance [dronecount>1 ? "drones" : "drone"] this round." + mode.declare_completion()//To declare normal completion. //calls auto_declare_completion_* for all modes diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index ad182d78..54b9ede6 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -30,7 +30,7 @@ /datum/game_mode/malfunction/pre_setup() for(var/mob/new_player/player in player_list) - if(player.mind && player.mind.assigned_role == "AI") + if(player.mind && player.mind.assigned_role == "AI" && (player.client.prefs.be_special & BE_MALF)) malf_ai+=player.mind if(malf_ai.len) return 1 diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index fe3df584..788ec569 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -358,7 +358,7 @@ datum/objective/escape if(!location) return 0 - if(istype(location, /turf/simulated/shuttle/floor4)) // Fails tratiors if they are in the shuttle brig -- Polymorph + if(istype(location, /turf/simulated/shuttle/floor4)) // Fails traitors if they are in the shuttle brig -- Polymorph if(istype(owner.current, /mob/living/carbon)) var/mob/living/carbon/C = owner.current if (!C.handcuffed) diff --git a/code/game/gamemodes/revolution/rp-revolution.dm b/code/game/gamemodes/revolution/rp-revolution.dm index 963579af..2fdf8af2 100644 --- a/code/game/gamemodes/revolution/rp-revolution.dm +++ b/code/game/gamemodes/revolution/rp-revolution.dm @@ -45,7 +45,7 @@ for (var/obj/machinery/computer/communications/comm in world) if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "paper - 'Cent. Com. Status Summary'" + intercept.name = "Cent. Com. Status Summary" intercept.info = intercepttext comm.messagetitle.Add("Cent. Com. Status Summary") @@ -116,7 +116,7 @@ for (var/obj/machinery/computer/communications/comm in world) if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "paper - 'Cent. Com. Status Summary'" + intercept.name = "Cent. Com. Status Summary" intercept.info = intercepttext comm.messagetitle.Add("Cent. Com. Status Summary") @@ -134,7 +134,7 @@ for (var/obj/machinery/computer/communications/comm in world) if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "paper - 'Cent. Com. Status Summary'" + intercept.name = "Cent. Com. Status Summary" intercept.info = intercepttext comm.messagetitle.Add("Cent. Com. Status Summary") diff --git a/code/game/gamemodes/revolution/rp_revolution.dm b/code/game/gamemodes/revolution/rp_revolution.dm index 2e10ec1b..fa64d90b 100644 --- a/code/game/gamemodes/revolution/rp_revolution.dm +++ b/code/game/gamemodes/revolution/rp_revolution.dm @@ -248,7 +248,7 @@ for (var/obj/machinery/computer/communications/comm in world) if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "paper - 'Cent. Com. Announcement'" + intercept.name = "Cent. Com. Announcement" intercept.info = message comm.messagetitle.Add("Cent. Com. Announcement") diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index b186d793..f79d1383 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -69,14 +69,14 @@ //testing("Assigning DNA blocks:") // Standard muts, imported from older code above. - //BLINDBLOCK = getAssignedBlock("BLIND", numsToAssign) - //DEAFBLOCK = getAssignedBlock("DEAF", numsToAssign) + BLINDBLOCK = getAssignedBlock("BLIND", numsToAssign) + DEAFBLOCK = getAssignedBlock("DEAF", numsToAssign) HULKBLOCK = getAssignedBlock("HULK", numsToAssign, DNA_HARD_BOUNDS) TELEBLOCK = getAssignedBlock("TELE", numsToAssign, DNA_HARD_BOUNDS) FIREBLOCK = getAssignedBlock("FIRE", numsToAssign, DNA_HARDER_BOUNDS) XRAYBLOCK = getAssignedBlock("XRAY", numsToAssign, DNA_HARDER_BOUNDS) CLUMSYBLOCK = getAssignedBlock("CLUMSY", numsToAssign) - //FAKEBLOCK = getAssignedBlock("FAKE", numsToAssign) + FAKEBLOCK = getAssignedBlock("FAKE", numsToAssign) // UNUSED! //COUGHBLOCK = getAssignedBlock("COUGH", numsToAssign) diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index 0c1fe311..5f3d9e1e 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -179,7 +179,6 @@ del(T) Z << "You are playing a Juggernaut. Though slow, you can withstand extreme punishment, and rip apart enemies and walls alike." Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." - Z.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall(Z) Z.cancel_camera() del(C) @@ -195,7 +194,6 @@ del(T) Z << "You are playing a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls." Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." - Z.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift(Z) Z.cancel_camera() del(C) @@ -211,10 +209,6 @@ del(T) Z << "You are playing an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, repair allied constructs (by clicking on them), and even create new constructs" Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." - Z.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser(Z) - Z.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/wall(Z) - Z.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/floor(Z) - Z.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone(Z) Z.cancel_camera() del(C) else diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index 6858157b..f4d98d1d 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -5,7 +5,7 @@ icon_state ="book" throw_speed = 1 throw_range = 5 - w_class = 1.0 + w_class = 2.0 flags = FPRINT | TABLEPASS var/uses = 5 var/temp = null diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index ad3d1477..7889a19b 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -92,7 +92,9 @@ H.equip_to_slot_or_del(new /obj/item/clothing/suit/apron(H), slot_wear_suit) H.equip_to_slot_or_del(new /obj/item/device/analyzer/plant_analyzer(H), slot_s_store) H.equip_to_slot_or_del(new /obj/item/device/pda/botanist(H), slot_belt) - if(H.backbag == 1) + if(H.backbag == 3) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_hyd(H), slot_back) + else if(H.backbag == 1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) else H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index 64b2738d..e0940ef2 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -71,6 +71,8 @@ H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/virologist(H), slot_wear_suit) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/virologist(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/mask/surgical(H), slot_wear_mask) + if(H.backbag == 3) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_vir(H), slot_back) if("Medical Doctor") H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) @@ -120,7 +122,9 @@ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/device/pda/chemist(H), slot_belt) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/chemist(H), slot_wear_suit) - if(H.backbag == 1) + if(H.backbag == 3) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_chem(H), slot_back) + else if(H.backbag == 1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) else H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) @@ -149,7 +153,9 @@ H.equip_to_slot_or_del(new /obj/item/device/pda/geneticist(H), slot_belt) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/genetics(H), slot_wear_suit) H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store) - if(H.backbag == 1) + if(H.backbag == 3) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_gen(H), slot_back) + else if(H.backbag == 1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) else H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index 8e8a210c..bb2c3f38 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -27,7 +27,9 @@ H.equip_to_slot_or_del(new /obj/item/device/pda/heads/rd(H), slot_belt) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) H.equip_to_slot_or_del(new /obj/item/weapon/clipboard(H), slot_l_hand) - if(H.backbag == 1) + if(H.backbag == 3) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_tox(H), slot_back) + else if(H.backbag == 1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) else H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) @@ -53,9 +55,11 @@ H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(H), slot_l_ear) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/device/pda/toxins(H), slot_belt) + H.equip_to_slot_or_del(new /obj/item/device/pda/science(H), slot_belt) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(H), slot_wear_suit) - if(H.backbag == 1) + if(H.backbag == 3) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_tox(H), slot_back) + else if(H.backbag == 1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) else H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) @@ -80,9 +84,11 @@ H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(H), slot_l_ear) H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/device/pda/toxins(H), slot_belt) + H.equip_to_slot_or_del(new /obj/item/device/pda/science(H), slot_belt) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(H), slot_wear_suit) - if(H.backbag == 1) + if(H.backbag == 3) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_tox(H), slot_back) + else if(H.backbag == 1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) else H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index b7d6ad8e..c400185a 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -282,6 +282,7 @@ dat += "" for(var/datum/organ/external/e in occupant.organs) + dat += "" var/AN = "" var/open = "" @@ -307,13 +308,15 @@ robot = "Prosthetic:" if(e.open) open = "Open:" + var/unknown_body = 0 for(var/I in e.implants) if(is_type_in_list(I,known_implants)) imp += "[I] implanted:" else unknown_body++ - if(unknown_body) + + if(unknown_body || e.hidden) imp += "Unknown body present:" if(!AN && !open && !infected & !imp) AN = "None:" diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index c4fc95d9..e5b07ca8 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -187,8 +187,8 @@ var/heat_capacity = gas.heat_capacity() var/energy_used = min( abs( heat_capacity*(gas.temperature - target_temperature) ), MAX_ENERGY_CHANGE) - //Use power. Assuming that each power unit represents 1000 watts.... - use_power(energy_used/1000, ENVIRON) + //Use power. Assuming that each power unit represents 1 watts.... + use_power(energy_used, ENVIRON) //We need to cool ourselves. if(environment.temperature > target_temperature) @@ -956,109 +956,29 @@ table tr:first-child th:first-child { border: none;} return output /obj/machinery/alarm/Topic(href, href_list) - - if(href_list["rcon"]) - rcon_setting = text2num(href_list["rcon"]) - - if ( (get_dist(src, usr) > 1 )) - if (!istype(usr, /mob/living/silicon)) - usr.machine = null - usr << browse(null, "window=air_alarm") - usr << browse(null, "window=AAlarmwires") - return + if(..() || !( Adjacent(usr) || istype(usr, /mob/living/silicon)) ) // dont forget calling super in machine Topics -walter0o + usr.machine = null + usr << browse(null, "window=air_alarm") + usr << browse(null, "window=AAlarmwires") + return add_fingerprint(usr) - usr.machine = src - - if(href_list["command"]) - var/device_id = href_list["id_tag"] - switch(href_list["command"]) - if( "power", - "adjust_external_pressure", - "set_external_pressure", - "checks", - "co2_scrub", - "tox_scrub", - "n2o_scrub", - "panic_siphon", - "scrubbing") - - send_signal(device_id, list(href_list["command"] = text2num(href_list["val"]) ) ) - - if("set_threshold") - var/env = href_list["env"] - var/threshold = text2num(href_list["var"]) - var/list/selected = TLV[env] - var/list/thresholds = list("lower bound", "low warning", "high warning", "upper bound") - var/newval = input("Enter [thresholds[threshold]] for [env]", "Alarm triggers", selected[threshold]) as null|num - if (isnull(newval) || ..() || (locked && issilicon(usr))) - return - if (newval<0) - selected[threshold] = -1.0 - else if (env=="temperature" && newval>5000) - selected[threshold] = 5000 - else if (env=="pressure" && newval>50*ONE_ATMOSPHERE) - selected[threshold] = 50*ONE_ATMOSPHERE - else if (env!="temperature" && env!="pressure" && newval>200) - selected[threshold] = 200 - else - newval = round(newval,0.01) - selected[threshold] = newval - if(threshold == 1) - if(selected[1] > selected[2]) - selected[2] = selected[1] - if(selected[1] > selected[3]) - selected[3] = selected[1] - if(selected[1] > selected[4]) - selected[4] = selected[1] - if(threshold == 2) - if(selected[1] > selected[2]) - selected[1] = selected[2] - if(selected[2] > selected[3]) - selected[3] = selected[2] - if(selected[2] > selected[4]) - selected[4] = selected[2] - if(threshold == 3) - if(selected[1] > selected[3]) - selected[1] = selected[3] - if(selected[2] > selected[3]) - selected[2] = selected[3] - if(selected[3] > selected[4]) - selected[4] = selected[3] - if(threshold == 4) - if(selected[1] > selected[4]) - selected[1] = selected[4] - if(selected[2] > selected[4]) - selected[2] = selected[4] - if(selected[3] > selected[4]) - selected[3] = selected[4] - - apply_mode() - - if(href_list["screen"]) - screen = text2num(href_list["screen"]) - - if(href_list["atmos_unlock"]) - switch(href_list["atmos_unlock"]) - if("0") - air_doors_close(1) - if("1") - air_doors_open(1) - - if(href_list["atmos_alarm"]) - if (alarm_area.atmosalert(2)) - apply_danger_level(2) - update_icon() - - if(href_list["atmos_reset"]) - if (alarm_area.atmosalert(0)) - apply_danger_level(0) - update_icon() - - if(href_list["mode"]) - mode = text2num(href_list["mode"]) - apply_mode() - + usr.set_machine(src) + + // hrefs that can always be called -walter0o + if(href_list["rcon"]) + var/attempted_rcon_setting = text2num(href_list["rcon"]) + + switch(attempted_rcon_setting) + if(RCON_NO) + rcon_setting = RCON_NO + if(RCON_AUTO) + rcon_setting = RCON_AUTO + if(RCON_YES) + rcon_setting = RCON_YES + else + return + if(href_list["temperature"]) var/list/selected = TLV["temperature"] var/max_temperature = min(selected[3] - T0C, MAX_TEMPERATURE) @@ -1069,31 +989,126 @@ table tr:first-child th:first-child { border: none;} else target_temperature = input_temperature + T0C - if (href_list["AAlarmwires"]) - var/t1 = text2num(href_list["AAlarmwires"]) - if (!( istype(usr.equipped(), /obj/item/weapon/wirecutters) )) - usr << "You need wirecutters!" - return - if (isWireColorCut(t1)) - mend(t1) - else - cut(t1) - if (AAlarmwires == 0) - usr << "You cut last of wires inside [src]" - update_icon() - buildstage = 1 - return - - else if (href_list["pulse"]) - var/t1 = text2num(href_list["pulse"]) - if (!istype(usr.equipped(), /obj/item/device/multitool)) - usr << "You need a multitool!" - return - if (isWireColorCut(t1)) - usr << "You can't pulse a cut wire." - return - else - pulse(t1) + // hrefs that need the AA unlocked -walter0o + if(!locked || istype(usr, /mob/living/silicon)) + + if(href_list["command"]) + var/device_id = href_list["id_tag"] + switch(href_list["command"]) + if( "power", + "adjust_external_pressure", + "set_external_pressure", + "checks", + "co2_scrub", + "tox_scrub", + "n2o_scrub", + "panic_siphon", + "scrubbing") + + send_signal(device_id, list(href_list["command"] = text2num(href_list["val"]) ) ) + + if("set_threshold") + var/env = href_list["env"] + var/threshold = text2num(href_list["var"]) + var/list/selected = TLV[env] + var/list/thresholds = list("lower bound", "low warning", "high warning", "upper bound") + var/newval = input("Enter [thresholds[threshold]] for [env]", "Alarm triggers", selected[threshold]) as null|num + if (isnull(newval) || ..() || (locked && issilicon(usr))) + return + if (newval<0) + selected[threshold] = -1.0 + else if (env=="temperature" && newval>5000) + selected[threshold] = 5000 + else if (env=="pressure" && newval>50*ONE_ATMOSPHERE) + selected[threshold] = 50*ONE_ATMOSPHERE + else if (env!="temperature" && env!="pressure" && newval>200) + selected[threshold] = 200 + else + newval = round(newval,0.01) + selected[threshold] = newval + if(threshold == 1) + if(selected[1] > selected[2]) + selected[2] = selected[1] + if(selected[1] > selected[3]) + selected[3] = selected[1] + if(selected[1] > selected[4]) + selected[4] = selected[1] + if(threshold == 2) + if(selected[1] > selected[2]) + selected[1] = selected[2] + if(selected[2] > selected[3]) + selected[3] = selected[2] + if(selected[2] > selected[4]) + selected[4] = selected[2] + if(threshold == 3) + if(selected[1] > selected[3]) + selected[1] = selected[3] + if(selected[2] > selected[3]) + selected[2] = selected[3] + if(selected[3] > selected[4]) + selected[4] = selected[3] + if(threshold == 4) + if(selected[1] > selected[4]) + selected[1] = selected[4] + if(selected[2] > selected[4]) + selected[2] = selected[4] + if(selected[3] > selected[4]) + selected[3] = selected[4] + + apply_mode() + + if(href_list["screen"]) + screen = text2num(href_list["screen"]) + + if(href_list["atmos_unlock"]) + switch(href_list["atmos_unlock"]) + if("0") + air_doors_close(1) + if("1") + air_doors_open(1) + + if(href_list["atmos_alarm"]) + if (alarm_area.atmosalert(2)) + apply_danger_level(2) + update_icon() + + if(href_list["atmos_reset"]) + if (alarm_area.atmosalert(0)) + apply_danger_level(0) + update_icon() + + if(href_list["mode"]) + mode = text2num(href_list["mode"]) + apply_mode() + + // hrefs that need the AA wires exposed, note that borgs should be in range here too -walter0o + if(wiresexposed && Adjacent(usr)) + + if (href_list["AAlarmwires"]) + var/t1 = text2num(href_list["AAlarmwires"]) + if (!( istype(usr.equipped(), /obj/item/weapon/wirecutters) )) + usr << "You need wirecutters!" + return + if (isWireColorCut(t1)) + mend(t1) + else + cut(t1) + if (AAlarmwires == 0) + usr << "You cut last of wires inside [src]" + update_icon() + buildstage = 1 + return + + else if (href_list["pulse"]) + var/t1 = text2num(href_list["pulse"]) + if (!istype(usr.equipped(), /obj/item/device/multitool)) + usr << "You need a multitool!" + return + if (isWireColorCut(t1)) + usr << "You can't pulse a cut wire." + return + else + pulse(t1) updateUsrDialog() diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 4e3db2ad..6af4d627 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -275,10 +275,15 @@ update_flag /obj/machinery/portable_atmospherics/canister/Topic(href, href_list) - //Do not use "if(..()) return" here, canisters will stop working in unpowered areas like space or on the derelict. + //Do not use "if(..()) return" here, canisters will stop working in unpowered areas like space or on the derelict. // yeah but without SOME sort of Topic check any dick can mess with them via exploits as he pleases -walter0o if (!istype(src.loc, /turf)) return 0 - + + if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) // exploit protection -walter0o + usr << browse(null, "window=canister") + onclose(usr, "canister") + return + if(href_list["toggle"]) if (valve_open) if (holding) diff --git a/code/game/machinery/bees_items.dm b/code/game/machinery/bees_items.dm index 01ed5bfa..e02a0a1a 100644 --- a/code/game/machinery/bees_items.dm +++ b/code/game/machinery/bees_items.dm @@ -102,21 +102,22 @@ h1 {font-size: 18px; margin: 15px 0px 5px;} h2 {font-size: 15px; margin: 15px 0px 5px;} li {margin: 2px 0px 2px 15px;} - ul {list-style: none; margin: 5px; padding: 0px;} + ul {margin: 5px; padding: 0px;} ol {margin: 5px; padding: 0px 15px;} + body {font-size: 13px; font-family: Verdana;} -

Raising Bees

+

Raising Bees

Bees are loving but fickle creatures. Don't mess with their hive and stay away from any clusters of them, and you'll avoid their ire. Sometimes, you'll need to dig around in there for those delicious sweeties though - in that case make sure you wear sealed protection gear and carry an extinguisher or smoker with you - any bees chasing you, once calmed down, can thusly be netted and returned safely to the hive. - Beezeez is a cure-all panacea for them, but use it too much and the hive may grow to apocalyptic proportions. Other than that, bees are excellent pets + BeezEez is a cure-all panacea for them, but use it too much and the hive may grow to apocalyptic proportions. Other than that, bees are excellent pets for all the family and are excellent caretakers of one's garden: having a hive or two around will aid in the longevity and growth rate of plants, and aid them in fighting off poisons and disease. - - "} + + "} diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm index b944636b..6e084931 100644 --- a/code/game/machinery/bots/ed209bot.dm +++ b/code/game/machinery/bots/ed209bot.dm @@ -231,8 +231,6 @@ Auto Patrol: []"}, continue if (istype(C, /mob/living/carbon/human)) threatlevel = src.assess_perp(C) - else if ((istype(C, /mob/living/carbon/monkey)) && (C.client) && (ticker.mode.name == "monkey")) - threatlevel = 4 //src.speak(C.real_name + text(": threat: []", threatlevel)) if (threatlevel < 4 ) continue @@ -271,7 +269,7 @@ Auto Patrol: []"}, walk_to(src,0) if (target) // make sure target exists - if (get_dist(src, src.target) <= 1) // if right next to perp + if (Adjacent(target)) // if right next to perp playsound(src.loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) src.icon_state = "[lasercolor]ed209-c" spawn(2) @@ -637,8 +635,6 @@ Auto Patrol: []"}, if (istype(C, /mob/living/carbon/human)) src.threatlevel = src.assess_perp(C) - else if ((istype(C, /mob/living/carbon/monkey)) && (C.client) && (ticker.mode.name == "monkey")) - src.threatlevel = 4 if (!src.threatlevel) continue @@ -735,7 +731,7 @@ Auto Patrol: []"}, /obj/machinery/bot/ed209/Bump(M as mob|obj) //Leave no door unopened! if ((istype(M, /obj/machinery/door)) && (!isnull(src.botcard))) var/obj/machinery/door/D = M - if (!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard)) + if (!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard) && !istype(D,/obj/machinery/door/poddoor)) D.open() src.frustration = 0 else if ((istype(M, /mob/living/)) && (!src.anchored)) diff --git a/code/game/machinery/bots/farmbot.dm b/code/game/machinery/bots/farmbot.dm index fe110939..b6f81984 100644 --- a/code/game/machinery/bots/farmbot.dm +++ b/code/game/machinery/bots/farmbot.dm @@ -540,10 +540,9 @@ var/obj/item/weapon/farmbot_arm_assembly/A = new /obj/item/weapon/farmbot_arm_assembly A.loc = src.loc - A.layer = 20 user << "You add the robot arm to the [src]" src.loc = A //Place the water tank into the assembly, it will be needed for the finished bot - + user.u_equip(S) del(S) /obj/item/weapon/farmbot_arm_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -552,18 +551,21 @@ src.build_step++ user << "You add the plant analyzer to [src]!" src.name = "farmbot assembly" + user.u_equip(W) del(W) else if(( istype(W, /obj/item/weapon/reagent_containers/glass/bucket)) && (src.build_step == 1)) src.build_step++ user << "You add a bucket to [src]!" src.name = "farmbot assembly with bucket" + user.u_equip(W) del(W) else if(( istype(W, /obj/item/weapon/minihoe)) && (src.build_step == 2)) src.build_step++ user << "You add a minihoe to [src]!" src.name = "farmbot assembly with bucket and minihoe" + user.u_equip(W) del(W) else if((isprox(W)) && (src.build_step == 3)) @@ -575,6 +577,7 @@ S.tank = wTank S.loc = get_turf(src) S.name = src.created_name + user.u_equip(W) del(W) del(src) @@ -587,3 +590,6 @@ return src.created_name = t + +/obj/item/weapon/farmbot_arm_assembly/attack_hand(mob/user as mob) + return //it's a converted watertank, no you cannot pick it up and put it in your backpack \ No newline at end of file diff --git a/code/game/machinery/bots/medbot.dm b/code/game/machinery/bots/medbot.dm index 6eabb2d0..f0c649ac 100644 --- a/code/game/machinery/bots/medbot.dm +++ b/code/game/machinery/bots/medbot.dm @@ -284,7 +284,7 @@ continue - if(src.patient && (get_dist(src,src.patient) <= 1)) + if(src.patient && Adjacent(patient)) if(!src.currently_healing) src.currently_healing = 1 src.frustration = 0 @@ -480,7 +480,7 @@ /obj/machinery/bot/medbot/Bump(M as mob|obj) //Leave no door unopened! if ((istype(M, /obj/machinery/door)) && (!isnull(src.botcard))) var/obj/machinery/door/D = M - if (!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard)) + if (!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard) && !istype(D,/obj/machinery/door/poddoor)) D.open() src.frustration = 0 else if ((istype(M, /mob/living/)) && (!src.anchored)) diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm index 7cf1ddc6..3aa31527 100644 --- a/code/game/machinery/bots/secbot.dm +++ b/code/game/machinery/bots/secbot.dm @@ -219,7 +219,7 @@ Auto Patrol: []"}, walk_to(src,0) if(target) // make sure target exists - if(get_dist(src, src.target) <= 1 && isturf(src.target.loc)) // if right next to perp + if(Adjacent(target)) // if right next to perp if(istype(src.target,/mob/living/carbon)) playsound(src.loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) src.icon_state = "secbot-c" @@ -600,8 +600,6 @@ Auto Patrol: []"}, if(istype(C, /mob/living/carbon/human)) src.threatlevel = src.assess_perp(C) - else if((src.idcheck) && (istype(C, /mob/living/carbon/monkey))) - src.threatlevel = 4 else if(istype(M, /mob/living/simple_animal/hostile)) if(M.stat == DEAD) @@ -682,7 +680,7 @@ Auto Patrol: []"}, /obj/machinery/bot/secbot/Bump(M as mob|obj) //Leave no door unopened! if((istype(M, /obj/machinery/door)) && (!isnull(src.botcard))) var/obj/machinery/door/D = M - if(!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard)) + if(!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard) && !istype(D,/obj/machinery/door/poddoor)) D.open() src.frustration = 0 else if((istype(M, /mob/living/)) && (!src.anchored)) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 148514f7..966741aa 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -215,7 +215,7 @@ /obj/machinery/camera/proc/cancelCameraAlarm() alarm_on = 0 for(var/mob/living/silicon/S in mob_list) - S.cancelAlarm("Camera", get_area(src), list(src), src) + S.cancelAlarm("Camera", get_area(src), src) /obj/machinery/camera/proc/can_use() if(!status) diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm index 6059878e..d672af55 100644 --- a/code/game/machinery/camera/motion.dm +++ b/code/game/machinery/camera/motion.dm @@ -42,14 +42,14 @@ /obj/machinery/camera/proc/cancelAlarm() if (detectTime == -1) for (var/mob/living/silicon/aiPlayer in player_list) - if (status) aiPlayer.cancelAlarm("Motion", src.loc.loc) + if (status) aiPlayer.cancelAlarm("Motion", get_area(src), src) detectTime = 0 return 1 /obj/machinery/camera/proc/triggerAlarm() if (!detectTime) return 0 for (var/mob/living/silicon/aiPlayer in player_list) - if (status) aiPlayer.triggerAlarm("Motion", src.loc.loc, src) + if (status) aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src) detectTime = -1 return 1 diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index bd001641..42f72bc6 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -10,6 +10,7 @@ power_channel = EQUIP var/obj/item/weapon/cell/charging = null var/chargelevel = -1 + var/efficiency = 0.875 //<1.0 means some power is lost in the charging process, >1.0 means free energy. proc updateicon() icon_state = "ccharger[charging ? 1 : 0]" @@ -91,8 +92,10 @@ //world << "ccpt [charging] [stat]" if(!charging || (stat & (BROKEN|NOPOWER)) || !anchored) return - - use_power(200) //this used to use CELLRATE, but CELLRATE is fucking awful. feel free to fix this properly! - charging.give(175) //inefficiency. - + + var/power_used = 100000 //for 200 units of charge. Yes, thats right, 100 kW. Is something wrong with CELLRATE? + + power_used = charging.give(power_used*CELLRATE*efficiency) + use_power(power_used) + updateicon() diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 7c3cfdbf..523d73ae 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -162,7 +162,7 @@ spawn(30) src.eject_wait = 0 - var/mob/living/carbon/human/H = new /mob/living/carbon/human(src) + var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species) occupant = H if(!R.dna.real_name) //to prevent null names @@ -212,10 +212,8 @@ if(R.dna.species == "Human") //no more xenos losing ears/tentacles H.h_style = pick("Bedhead", "Bedhead 2", "Bedhead 3") - H.set_species(R.dna.species) - - //for(var/datum/language/L in languages) - // H.add_language(L.name) + for(var/datum/language/L in R.languages) + H.add_language(L.name) H.suiciding = 0 src.attempting = 0 return 1 @@ -435,7 +433,7 @@ */ /obj/item/weapon/paper/Cloning - name = "paper - 'H-87 Cloning Apparatus Manual" + name = "H-87 Cloning Apparatus Manual" info = {"

Getting Started

Congratulations, your station has purchased the H-87 industrial cloning device!
Using the H-87 is almost as simple as brain surgery! Simply insert the target humanoid into the scanning chamber and select the scan option to create a new profile!
diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm index cbc89ac8..f4a80c0a 100644 --- a/code/game/machinery/computer/HolodeckControl.dm +++ b/code/game/machinery/computer/HolodeckControl.dm @@ -315,7 +315,7 @@ if(world.time < (last_change + 15))//To prevent super-spam clicking, reduced process size and annoyance -Sieve return for(var/mob/M in range(3,src)) - M.show_message("\b ERROR. Recalibrating projetion apparatus.") + M.show_message("\b ERROR. Recalibrating projection apparatus.") last_change = world.time return @@ -447,6 +447,8 @@ if(isrobot(user)) return + + ..() /obj/structure/table/holotable/wood name = "table" diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index c320e674..d6cb0ede 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -2,6 +2,7 @@ name = "AI System Integrity Restorer" icon = 'icons/obj/computer.dmi' icon_state = "ai-fixer" + circuit = /obj/item/weapon/circuitboard/aifixer req_access = list(access_captain, access_robotics, access_heads) var/mob/living/silicon/ai/occupant = null var/active = 0 @@ -11,43 +12,13 @@ /obj/machinery/computer/aifixer/attackby(I as obj, user as mob) -/* - if(istype(I, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, 20)) - if (src.stat & BROKEN) - user << "\blue The broken glass falls out." - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - new /obj/item/weapon/shard( src.loc ) - var/obj/item/weapon/circuitboard/robotics/M = new /obj/item/weapon/circuitboard/robotics( A ) - for (var/obj/C in src) - C.loc = src.loc - M.id = src.id - A.circuit = M - A.state = 3 - A.icon_state = "3" - A.anchored = 1 - del(src) - else - user << "\blue You disconnect the monitor." - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - var/obj/item/weapon/circuitboard/robotics/M = new /obj/item/weapon/circuitboard/robotics( A ) - for (var/obj/C in src) - C.loc = src.loc - M.id = src.id - A.circuit = M - A.state = 4 - A.icon_state = "4" - A.anchored = 1 - del(src) -*/ if(istype(I, /obj/item/device/aicard)) if(stat & (NOPOWER|BROKEN)) user << "This terminal isn't functioning right now, get it working!" return I:transfer_ai("AIFIXER","AICARD",src,user) - - //src.attack_hand(user) + + ..() return /obj/machinery/computer/aifixer/attack_ai(var/mob/user as mob) diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 512c37ca..4cc773c5 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -238,27 +238,10 @@ src.updateUsrDialog() - else if(istype(I, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, 20)) - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - var/obj/item/weapon/circuitboard/arcade/M = new /obj/item/weapon/circuitboard/arcade( A ) - for (var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.anchored = 1 + else + ..() - if (src.stat & BROKEN) - user << "\blue The broken glass falls out." - new /obj/item/weapon/shard( src.loc ) - A.state = 3 - A.icon_state = "3" - else - user << "\blue You disconnect the monitor." - A.state = 4 - A.icon_state = "4" - del(src) /obj/machinery/computer/arcade/emp_act(severity) if(stat & (NOPOWER|BROKEN)) ..(severity) diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 1233d175..cb454ceb 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -109,6 +109,10 @@ name = "Circuit board (Robotics Control)" build_path = "/obj/machinery/computer/robotics" origin_tech = "programming=3" +/obj/item/weapon/circuitboard/drone_control + name = "Circuit board (Drone Control)" + build_path = "/obj/machinery/computer/drone_control" + origin_tech = "programming=3" /obj/item/weapon/circuitboard/cloning name = "Circuit board (Cloning)" build_path = "/obj/machinery/computer/cloning" @@ -281,14 +285,15 @@ /obj/item/weapon/circuitboard/rdconsole/attackby(obj/item/I as obj, mob/user as mob) if(istype(I,/obj/item/weapon/screwdriver)) + user.visible_message("\blue \the [user] adjusts the jumper on the [src]'s access protocol pins.", "\blue You adjust the jumper on the access protocol pins.") if(src.build_path == "/obj/machinery/computer/rdconsole/core") src.name = "Circuit Board (RD Console - Robotics)" src.build_path = "/obj/machinery/computer/rdconsole/robotics" - user << "\blue Access protocols succesfully updated." + user << "\blue Access protocols set to robotics." else src.name = "Circuit Board (RD Console)" src.build_path = "/obj/machinery/computer/rdconsole/core" - user << "\blue Defaulting access protocols." + user << "\blue Access protocols set to default." return /obj/structure/computerframe/attackby(obj/item/P as obj, mob/user as mob) diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index 1d724b83..fcf525cc 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -108,10 +108,57 @@ header += "
" var/jobs_all = "" - var/list/alljobs = (istype(src,/obj/machinery/computer/card/centcom)? get_all_centcom_jobs() : joblist) + "Custom" - for(var/job in alljobs) - jobs_all += "[replacetext(job, " ", " ")] " //make sure there isn't a line break in the middle of a job + var/counter = 0 + jobs_all += "" + jobs_all += ""//Captain in special because he is head of heads ~Intercross21 + jobs_all += "" + jobs_all += "" + + counter = 0 + jobs_all += ""//Orange + for(var/job in engineering_positions) + counter++ + if(counter >= 6) + jobs_all += "" + counter = 0 + jobs_all += "" + + counter = 0 + jobs_all += ""//Green + for(var/job in medical_positions) + counter++ + if(counter >= 6) + jobs_all += "" + counter = 0 + jobs_all += "" + + counter = 0 + jobs_all += ""//Purple + for(var/job in science_positions) + counter++ + if(counter >= 6) + jobs_all += "" + counter = 0 + jobs_all += "" + + counter = 0 + jobs_all += ""//Grey + for(var/job in civilian_positions) + counter++ + if(counter >= 6) + jobs_all += "" + counter = 0 + jobs_all += "" + + if(istype(src,/obj/machinery/computer/card/centcom)) + counter = 0 + jobs_all += ""//Brown + for(var/job in get_all_centcom_jobs()) + if(counter >= 6) + jobs_all += "" + counter = 0 + jobs_all += "" var/body if (authenticated && modify) @@ -138,7 +185,7 @@ } function hideAll(){ var allJobsSlot = document.getElementById('alljobsslot'); - allJobsSlot.innerHTML = "show"; + allJobsSlot.innerHTML = "[(modify.assignment) ? modify.assignment : "Unassgied"]"; } "} carddesc += "" @@ -255,7 +302,7 @@ if (authenticated) var/t1 = href_list["assign_target"] if(t1 == "Custom") - var/temp_t = copytext(sanitize(input("Enter a custom job assignment.","Assignment")),1,MAX_MESSAGE_LEN) + var/temp_t = copytext(sanitize(input("Enter a custom job assignment.","Assignment")),1,45) //let custom jobs function as an impromptu alt title, mainly for sechuds if(temp_t && modify) modify.assignment = temp_t @@ -312,7 +359,7 @@ t1 += data_core.get_manifest(0) // make it monochrome P.info = t1 - P.name = "paper- 'Crew Manifest'" + P.name = text("Crew Manifest ([])", worldtime2text()) printing = null if (modify) modify.name = text("[modify.registered_name]'s ID Card ([modify.assignment])") diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 293046b0..9ce8ccb4 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -361,6 +361,7 @@ R.id= copytext(md5(subject.real_name), 2, 6) R.name=R.dna.real_name R.types=DNA2_BUF_UI|DNA2_BUF_UE|DNA2_BUF_SE + R.languages=subject.languages //Add an implant if needed var/obj/item/weapon/implant/health/imp = locate(/obj/item/weapon/implant/health, subject) diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index c47eb1f9..b289bcaa 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -95,6 +95,11 @@ stat |= BROKEN update_icon() +/obj/machinery/computer/proc/decode(text) + // Adds line breaks + text = replacetext(text, "\n", "
") + return text + /obj/machinery/computer/attackby(I as obj, user as mob) if(istype(I, /obj/item/weapon/screwdriver) && circuit) diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 133b622f..cf9f292f 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -16,6 +16,14 @@ var/temp = null var/printing = null +/obj/machinery/computer/med_data/attackby(obj/item/O as obj, user as mob) + if(istype(O, /obj/item/weapon/card/id) && !scan) + usr.drop_item() + O.loc = src + scan = O + user << "You insert [O]." + ..() + /obj/machinery/computer/med_data/attack_ai(user as mob) return src.attack_hand(user) @@ -70,7 +78,7 @@ else dat += "General Record Lost!
" if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2))) - dat += text("
\n
Medical Data

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

", src, src.active2.fields["b_type"], src, src.active2.fields["b_dna"], src, src.active2.fields["mi_dis"], src, src.active2.fields["mi_dis_d"], src, src.active2.fields["ma_dis"], src, src.active2.fields["ma_dis_d"], src, src.active2.fields["alg"], src, src.active2.fields["alg_d"], src, src.active2.fields["cdi"], src, src.active2.fields["cdi_d"], src, src.active2.fields["notes"]) + dat += text("
\n
Medical Data

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

", src, src.active2.fields["b_type"], src, src.active2.fields["b_dna"], src, src.active2.fields["mi_dis"], src, src.active2.fields["mi_dis_d"], src, src.active2.fields["ma_dis"], src, src.active2.fields["ma_dis_d"], src, src.active2.fields["alg"], src, src.active2.fields["alg_d"], src, src.active2.fields["cdi"], src, src.active2.fields["cdi_d"], src, decode(src.active2.fields["notes"])) var/counter = 1 while(src.active2.fields[text("com_[]", counter)]) dat += text("[]
Delete Entry

", src.active2.fields[text("com_[]", counter)], src, counter) @@ -294,7 +302,7 @@ src.active2.fields["cdi_d"] = t1 if("notes") if (istype(src.active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize notes:", "Med. records", src.active2.fields["notes"], null) as message),1,MAX_MESSAGE_LEN) + var/t1 = copytext(html_encode(input("Please summarize notes:", "Med. records", html_decode(src.active2.fields["notes"]), null) as message),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2)) return src.active2.fields["notes"] = t1 @@ -463,23 +471,30 @@ if (href_list["print_p"]) if (!( src.printing )) src.printing = 1 + var/datum/data/record/record1 = null + var/datum/data/record/record2 = null + if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))) + record1 = active1 + if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2))) + record2 = active2 sleep(50) var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.loc ) P.info = "
Medical Record

" - if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))) - P.info += text("Name: [] ID: []
\nSex: []
\nAge: []
\nFingerprint: []
\nPhysical Status: []
\nMental Status: []
", src.active1.fields["name"], src.active1.fields["id"], src.active1.fields["sex"], src.active1.fields["age"], src.active1.fields["fingerprint"], src.active1.fields["p_stat"], src.active1.fields["m_stat"]) + if (record1) + P.info += text("Name: [] ID: []
\nSex: []
\nAge: []
\nFingerprint: []
\nPhysical Status: []
\nMental Status: []
", record1.fields["name"], record1.fields["id"], record1.fields["sex"], record1.fields["age"], record1.fields["fingerprint"], record1.fields["p_stat"], record1.fields["m_stat"]) + P.name = text("Medical Record ([])", record1.fields["name"]) else P.info += "General Record Lost!
" - if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2))) - P.info += text("
\n
Medical Data

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

", src.active2.fields["b_type"], src.active2.fields["b_dna"], src.active2.fields["mi_dis"], src.active2.fields["mi_dis_d"], src.active2.fields["ma_dis"], src.active2.fields["ma_dis_d"], src.active2.fields["alg"], src.active2.fields["alg_d"], src.active2.fields["cdi"], src.active2.fields["cdi_d"], src.active2.fields["notes"]) + P.name = "Medical Record" + if (record2) + P.info += text("
\n
Medical Data

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

", record2.fields["b_type"], record2.fields["b_dna"], record2.fields["mi_dis"], record2.fields["mi_dis_d"], record2.fields["ma_dis"], record2.fields["ma_dis_d"], record2.fields["alg"], record2.fields["alg_d"], record2.fields["cdi"], record2.fields["cdi_d"], decode(record2.fields["notes"])) var/counter = 1 - while(src.active2.fields[text("com_[]", counter)]) - P.info += text("[]
", src.active2.fields[text("com_[]", counter)]) + while(record2.fields[text("com_[]", counter)]) + P.info += text("[]
", record2.fields[text("com_[]", counter)]) counter++ else P.info += "Medical Record Lost!
" P.info += "" - P.name = "paper- 'Medical Record'" src.printing = null src.add_fingerprint(usr) diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm index 0a5696ee..eeadf4de 100644 --- a/code/game/machinery/computer/pod.dm +++ b/code/game/machinery/computer/pod.dm @@ -4,6 +4,7 @@ name = "Pod Launch Control" desc = "A controll for launching pods. Some people prefer firing Mechas." icon_state = "computer_generic" + circuit = /obj/item/weapon/circuitboard/pod var/id = 1.0 var/obj/machinery/mass_driver/connected = null var/timing = 0.0 @@ -33,7 +34,7 @@ for(var/obj/machinery/door/poddoor/M in world) if(M.id == id) M.open() - return + sleep(20) for(var/obj/machinery/mass_driver/M in world) @@ -48,7 +49,7 @@ return return - +/* /obj/machinery/computer/pod/attackby(I as obj, user as mob) if(istype(I, /obj/item/weapon/screwdriver)) playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1) @@ -103,6 +104,7 @@ else attack_hand(user) return +*/ /obj/machinery/computer/pod/attack_ai(var/mob/user as mob) @@ -171,6 +173,12 @@ connected.power = t if(href_list["alarm"]) alarm() + if(href_list["drive"]) + for(var/obj/machinery/mass_driver/M in machines) + if(M.id == id) + M.power = connected.power + M.drive() + if(href_list["time"]) timing = text2num(href_list["time"]) if(href_list["tp"]) diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index f75e4f22..cdce6fdf 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -42,6 +42,8 @@ dat += "2. Emergency Full Destruct
" if(screen == 1) for(var/mob/living/silicon/robot/R in mob_list) + if(istype(R, /mob/living/silicon/robot/drone)) + continue //There's a specific console for drones. if(istype(user, /mob/living/silicon/ai)) if (R.connected_ai != user) continue @@ -220,8 +222,7 @@ while(src.timeleft) for(var/mob/living/silicon/robot/R in mob_list) - if(!R.scrambledcodes) + if(!R.scrambledcodes && !istype(R, /mob/living/silicon/robot/drone)) R.self_destruct() - return - + return \ No newline at end of file diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 4f138bad..bfb5341b 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -125,7 +125,7 @@ else dat += "General Record Lost!
" if ((istype(active2, /datum/data/record) && data_core.security.Find(active2))) - dat += text("
\n
Security Data

\nCriminal Status: []
\n
\nMinor Crimes: []
\nDetails: []
\n
\nMajor Crimes: []
\nDetails: []
\n
\nImportant Notes:
\n\t[]
\n
\n
Comments/Log

", src, active2.fields["criminal"], src, active2.fields["mi_crim"], src, active2.fields["mi_crim_d"], src, active2.fields["ma_crim"], src, active2.fields["ma_crim_d"], src, active2.fields["notes"]) + dat += text("
\n
Security Data

\nCriminal Status: []
\n
\nMinor Crimes: []
\nDetails: []
\n
\nMajor Crimes: []
\nDetails: []
\n
\nImportant Notes:
\n\t[]
\n
\n
Comments/Log

", src, active2.fields["criminal"], src, active2.fields["mi_crim"], src, active2.fields["mi_crim_d"], src, active2.fields["ma_crim"], src, active2.fields["ma_crim_d"], src, decode(active2.fields["notes"])) var/counter = 1 while(active2.fields[text("com_[]", counter)]) dat += text("[]
Delete Entry

", active2.fields[text("com_[]", counter)], src, counter) @@ -329,23 +329,30 @@ What a mess.*/ if ("Print Record") if (!( printing )) printing = 1 + var/datum/data/record/record1 = null + var/datum/data/record/record2 = null + if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) + record1 = active1 + if ((istype(active2, /datum/data/record) && data_core.security.Find(active2))) + record2 = active2 sleep(50) var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( loc ) P.info = "
Security Record

" - if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) - P.info += text("Name: [] ID: []
\nSex: []
\nAge: []
\nFingerprint: []
\nPhysical Status: []
\nMental Status: []
", active1.fields["name"], active1.fields["id"], active1.fields["sex"], active1.fields["age"], active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"]) + if (record1) + P.info += text("Name: [] ID: []
\nSex: []
\nAge: []
\nFingerprint: []
\nPhysical Status: []
\nMental Status: []
", record1.fields["name"], record1.fields["id"], record1.fields["sex"], record1.fields["age"], record1.fields["fingerprint"], record1.fields["p_stat"], record1.fields["m_stat"]) + P.name = text("Security Record ([])", record1.fields["name"]) else P.info += "General Record Lost!
" - if ((istype(active2, /datum/data/record) && data_core.security.Find(active2))) - P.info += text("
\n
Security Data

\nCriminal Status: []
\n
\nMinor Crimes: []
\nDetails: []
\n
\nMajor Crimes: []
\nDetails: []
\n
\nImportant Notes:
\n\t[]
\n
\n
Comments/Log

", active2.fields["criminal"], active2.fields["mi_crim"], active2.fields["mi_crim_d"], active2.fields["ma_crim"], active2.fields["ma_crim_d"], active2.fields["notes"]) + P.name = "Security Record" + if (record2) + P.info += text("
\n
Security Data

\nCriminal Status: []
\n
\nMinor Crimes: []
\nDetails: []
\n
\nMajor Crimes: []
\nDetails: []
\n
\nImportant Notes:
\n\t[]
\n
\n
Comments/Log

", record2.fields["criminal"], record2.fields["mi_crim"], record2.fields["mi_crim_d"], record2.fields["ma_crim"], record2.fields["ma_crim_d"], decode(record2.fields["notes"])) var/counter = 1 - while(active2.fields[text("com_[]", counter)]) - P.info += text("[]
", active2.fields[text("com_[]", counter)]) + while(record2.fields[text("com_[]", counter)]) + P.info += text("[]
", record2.fields[text("com_[]", counter)]) counter++ else P.info += "Security Record Lost!
" P.info += "" - P.name = "paper - 'Security Record'" printing = null updateUsrDialog() //RECORD DELETE @@ -481,7 +488,7 @@ What a mess.*/ active2.fields["ma_crim_d"] = t1 if("notes") if (istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please summarize notes:", "Secure. records", active2.fields["notes"], null) as message),1,MAX_MESSAGE_LEN) + var/t1 = copytext(html_encode(input("Please summarize notes:", "Secure. records", html_decode(active2.fields["notes"]), null) as message),1,MAX_MESSAGE_LEN) if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active2 != a2)) return active2.fields["notes"] = t1 diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm index 3068d993..27360e96 100644 --- a/code/game/machinery/computer/skills.dm +++ b/code/game/machinery/computer/skills.dm @@ -100,7 +100,7 @@ Fingerprint: [active1.fields["fingerprint"]]
\n \ Physical Status: [active1.fields["p_stat"]]
\n \ Mental Status: [active1.fields["m_stat"]]

\n \ - Employment/skills summary:
[active1.fields["notes"]]
\ + Employment/skills summary:
[decode(active1.fields["notes"])]
\
Command
SpecialCaptainCustom
Engineering
[replacetext(job, " ", " ")]
Medical
[replacetext(job, " ", " ")]
Science
[replacetext(job, " ", " ")]
Civilian
[replacetext(job, " ", " ")]
CentComm
[replacetext(job, " ", " ")]
Photo:
\
") else @@ -275,11 +275,11 @@ What a mess.*/ var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( loc ) P.info = "
Employment Record

" if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) - P.info += text("Name: [] ID: []
\nSex: []
\nAge: []
\nFingerprint: []
\nPhysical Status: []
\nMental Status: []
\nEmployment/Skills Summary:[]
", active1.fields["name"], active1.fields["id"], active1.fields["sex"], active1.fields["age"], active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"], active1.fields["notes"]) + P.info += text("Name: [] ID: []
\nSex: []
\nAge: []
\nFingerprint: []
\nPhysical Status: []
\nMental Status: []
\nEmployment/Skills Summary:
\n[]
", active1.fields["name"], active1.fields["id"], active1.fields["sex"], active1.fields["age"], active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"], decode(active1.fields["notes"])) else P.info += "General Record Lost!
" P.info += "" - P.name = "paper - 'Employment Record'" + P.name = "Employment Record ([active1.fields["name"]])" printing = null //RECORD DELETE if ("Delete All Records") @@ -302,7 +302,7 @@ What a mess.*/ temp += "No" //RECORD CREATE if ("New Record (General)") - + if(PDA_Manifest.len) PDA_Manifest.Cut() var/datum/data/record/G = new /datum/data/record() diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index 3a3252b0..eab70dd4 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -16,7 +16,7 @@ var/locked = 1 attack_self(mob/user as mob) - if (!ishuman(user)) + if (!ishuman(user) && !istype(user,/mob/living/silicon/robot/drone)) return ..(user) var/mob/living/carbon/human/H = user @@ -59,20 +59,24 @@ Topic(href, href_list) ..() - if (usr.stat || usr.restrained() || !ishuman(usr)) + if (usr.stat || usr.restrained() || (!ishuman(usr) && !istype(usr,/mob/living/silicon))) return if (href_list["close"]) usr << browse(null, "window=airlock") return if (href_list["login"]) - var/obj/item/I = usr.get_active_hand() - if (istype(I, /obj/item/device/pda)) - var/obj/item/device/pda/pda = I - I = pda.id - if (I && src.check_access(I)) + if(istype(usr,/mob/living/silicon)) src.locked = 0 - src.last_configurator = I:registered_name + src.last_configurator = usr.name + else + var/obj/item/I = usr.get_active_hand() + if (istype(I, /obj/item/device/pda)) + var/obj/item/device/pda/pda = I + I = pda.id + if (I && src.check_access(I)) + src.locked = 0 + src.last_configurator = I:registered_name if (locked) return diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index b79a9111..79ec51fd 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -33,6 +33,9 @@ var/const/HOLOPAD_MODE = 0 name = "\improper AI holopad" desc = "It's a floor-mounted device for projecting holographic images. It is activated remotely." icon_state = "holopad0" + + layer = TURF_LAYER+0.1 //Preventing mice and drones from sneaking under them. + var/mob/living/silicon/ai/master//Which AI, if any, is controlling the object? Only one AI may control a hologram at any time. var/last_request = 0 //to prevent request spam. ~Carn var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating. @@ -78,13 +81,13 @@ var/const/HOLOPAD_MODE = 0 /*This is the proc for special two-way communication between AI and holopad/people talking near holopad. For the other part of the code, check silicon say.dm. Particularly robot talk.*/ -/obj/machinery/hologram/holopad/hear_talk(mob/living/M, text) +/obj/machinery/hologram/holopad/hear_talk(mob/living/M, text, verb) if(M&&hologram&&master)//Master is mostly a safety in case lag hits or something. if(!master.say_understands(M))//The AI will be able to understand most mobs talking through the holopad. text = stars(text) var/name_used = M.GetVoice() //This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only. - var/rendered = "Holopad received, [name_used] [M.say_quote(text)]" + var/rendered = "Holopad received, [name_used] [verb], \"[text]\"" master.show_message(rendered, 2) return @@ -210,4 +213,4 @@ Holographic project of everything else. name = "hologram projector" desc = "It makes a hologram appear...with magnets or something..." icon = 'icons/obj/stationobjs.dmi' - icon_state = "hologram0" \ No newline at end of file + icon_state = "hologram0" diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index 04eab68b..b7cc3bdf 100644 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -1,6 +1,6 @@ /obj/machinery/igniter name = "igniter" - desc = "It's useful for igniting plasma." + desc = "It's useful for igniting flammable items." icon = 'icons/obj/stationobjs.dmi' icon_state = "igniter1" var/id = null @@ -14,8 +14,6 @@ return src.attack_hand(user) /obj/machinery/igniter/attack_paw(mob/user as mob) - if ((ticker && ticker.mode.name == "monkey")) - return src.attack_hand(user) return /obj/machinery/igniter/attack_hand(mob/user as mob) @@ -156,4 +154,4 @@ icon_state = "launcherbtt" active = 0 - return \ No newline at end of file + return diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index dbd34f7a..5974cce6 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -130,12 +130,25 @@ if(!isbroken) icon_state = icon_off - /******************* * Item Adding ********************/ /obj/machinery/smartfridge/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O, /obj/item/weapon/screwdriver)) + panel_open = !panel_open + user << "You [panel_open ? "open" : "close"] the maintenance panel." + overlays.Cut() + if(panel_open) + overlays += image(icon, icon_panel) + nanomanager.update_uis(src) + return + + if(istype(O, /obj/item/device/multitool)||istype(O, /obj/item/weapon/wirecutters)) + if(panel_open) + attack_hand(user) + return + if(!src.ispowered) user << "\The [src] is unpowered and useless." return @@ -154,6 +167,8 @@ user.visible_message("[user] has added \the [O] to \the [src].", \ "You add \the [O] to \the [src].") + nanomanager.update_uis(src) + else if(istype(O, /obj/item/weapon/storage/bag/plants)) var/obj/item/weapon/storage/bag/plants/P = O var/plants_loaded = 0 @@ -171,147 +186,155 @@ plants_loaded++ if(plants_loaded) - user.visible_message("[user] loads \the [src] with \the [P].", \ - "You load \the [src] with \the [P].") + user.visible_message( \ + "[user] loads \the [src] with \the [P].", \ + "You load \the [src] with \the [P].") if(P.contents.len > 0) user << "Some items are refused." + nanomanager.update_uis(src) + else user << "\The [src] smartly refuses [O]." return 1 - updateUsrDialog() - /obj/machinery/smartfridge/secure/attackby(var/obj/item/O as obj, var/mob/user as mob) if (istype(O, /obj/item/weapon/card/emag)) - src.emagged = 1 - user << "You short out the product lock on [src]" - return - else if(istype(O, /obj/item/weapon/screwdriver)) - src.panel_open = !src.panel_open - user << "You [src.panel_open ? "open" : "close"] the maintenance panel." - src.overlays.Cut() - if(src.panel_open) - src.overlays += image(src.icon, src.icon_panel) - src.updateUsrDialog() - return - else if(istype(O, /obj/item/device/multitool)||istype(O, /obj/item/weapon/wirecutters)) - if(src.panel_open) - attack_hand(user) + emagged = 1 + locked = -1 + user << "You short out the product lock on [src]." return + ..() - return /obj/machinery/smartfridge/attack_paw(mob/user as mob) - return src.attack_hand(user) + return attack_hand(user) /obj/machinery/smartfridge/attack_ai(mob/user as mob) return 0 /obj/machinery/smartfridge/attack_hand(mob/user as mob) - user.set_machine(src) - if(src.seconds_electrified != 0) - if(src.shock(user, 100)) + if(!ispowered) return + if(seconds_electrified != 0) + if(shock(user, 100)) return - interact(user) + + ui_interact(user) /******************* * SmartFridge Menu ********************/ -/obj/machinery/smartfridge/interact(mob/user as mob) - if(!src.ispowered) - return +/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + user.set_machine(src) - var/dat = "Select an item:
" + var/is_secure = istype(src,/obj/machinery/smartfridge/secure) - if (contents.len == 0) - dat += "No product loaded!" + var/data[0] + data["contents"] = null + data["wires"] = null + data["panel_open"] = panel_open + data["electrified"] = seconds_electrified > 0 + data["shoot_inventory"] = shoot_inventory + data["locked"] = locked + data["secure"] = is_secure + + var/list/items[0] + for (var/i=1 to length(item_quants)) + var/K = item_quants[i] + var/count = item_quants[K] + if (count > 0) + items.Add(list(list("display_name" = html_encode(capitalize(K)), "vend" = i, "quantity" = count))) + + if (items.len > 0) + data["contents"] = items + + var/list/vendwires = null + if (is_secure) + vendwires = list( + "Violet" = 1, + "Orange" = 2, + "Green" = 3) else - for (var/O in item_quants) - if(item_quants[O] > 0) - var/N = item_quants[O] - dat += "[capitalize(O)]:" - dat += " [N] " - dat += "Vend " - if(N > 5) - dat += "(x5)" - if(N > 10) - dat += "(x10)" - if(N > 25) - dat += "(x25)" - if(N > 1) - dat += "(All)" - dat += "
" - - dat += "
" - if(panel_open) - //One of the wires does absolutely nothing. - var/list/vendwires = list( + vendwires = list( "Blue" = 1, "Red" = 2, - "Black" = 3 - ) - dat += "


Access Panel
" - for(var/wiredesc in vendwires) - var/is_uncut = src.wires & APCWireColorToFlag[vendwires[wiredesc]] - dat += "[wiredesc] wire: " - if(!is_uncut) - dat += "Mend" - else - dat += "Cut " - dat += "Pulse " - dat += "
" + "Black" = 3) - dat += "
" - dat += "The orange light is [(src.seconds_electrified == 0) ? "off" : "on"].
" - dat += "The red light is [src.shoot_inventory ? "off" : "blinking"].
" - user << browse("[src] Supplies[dat]", "window=smartfridge") - return + var/list/vendor_wires[0] + for (var/wire in vendwires) + var is_uncut = wires & APCWireColorToFlag[vendwires[wire]] + vendor_wires.Add(list(list("wire" = wire, "cut" = !is_uncut, "index" = vendwires[wire]))) + + if (vendor_wires.len > 0) + data["wires"] = vendor_wires + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + ui = new(user, src, ui_key, "smartfridge.tmpl", src.name, 400, 500) + ui.set_initial_data(data) + ui.open() /obj/machinery/smartfridge/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) + if (..()) return 0 - if ((href_list["cutwire"]) && (src.panel_open)) - var/twire = text2num(href_list["cutwire"]) - if (!( istype(usr.get_active_hand(), /obj/item/weapon/wirecutters) )) - usr << "You need wirecutters!" - return - if (src.isWireColorCut(twire)) - src.mend(twire) - else - src.cut(twire) - else if ((href_list["pulsewire"]) && (src.panel_open)) - var/twire = text2num(href_list["pulsewire"]) - if (!istype(usr.get_active_hand(), /obj/item/device/multitool)) - usr << "You need a multitool!" - return - if (src.isWireColorCut(twire)) - usr << "You can't pulse a cut wire." - return - else - src.pulse(twire) - else if (href_list["vend"]) - var/N = href_list["vend"] + var/mob/user = usr + var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") + + src.add_fingerprint(user) + + if (href_list["close"]) + user.unset_machine() + ui.close() + return 0 + + if (href_list["vend"]) + var/index = text2num(href_list["vend"]) var/amount = text2num(href_list["amount"]) + var/K = item_quants[index] + var/count = item_quants[K] - if(item_quants[N] <= 0) // Sanity check, there are probably ways to press the button when it shouldn't be possible. - return + // Sanity check, there are probably ways to press the button when it shouldn't be possible. + if(count > 0) + item_quants[K] = max(count - amount, 0) - item_quants[N] = max(item_quants[N] - amount, 0) + var/i = amount + for(var/obj/O in contents) + if (O.name == K) + O.loc = loc + i-- + if (i <= 0) + return 1 - var/i = amount - for(var/obj/O in contents) - if(O.name == N) - O.loc = src.loc - i-- - if(i <= 0) - break - src.add_fingerprint(usr) - src.updateUsrDialog() - return + return 1 + + if (panel_open) + if (href_list["cutwire"]) + if (!( istype(usr.get_active_hand(), /obj/item/weapon/wirecutters) )) + user << "You need wirecutters!" + return 1 + + var/wire_index = text2num(href_list["cutwire"]) + if (isWireColorCut(wire_index)) + mend(wire_index) + else + cut(wire_index) + return 1 + + if (href_list["pulsewire"]) + if (!istype(usr.get_active_hand(), /obj/item/device/multitool)) + usr << "You need a multitool!" + return 1 + + var/wire_index = text2num(href_list["pulsewire"]) + if (isWireColorCut(wire_index)) + usr << "You can't pulse a cut wire." + return 1 + + pulse(wire_index) + return 1 + + return 0 /************* * Hacking @@ -332,7 +355,7 @@ /obj/machinery/smartfridge/proc/mend(var/wireColor) var/wireFlag = APCWireColorToFlag[wireColor] - var/wireIndex = APCWireColorToIndex[wireColor] //not used in this function + var/wireIndex = APCWireColorToIndex[wireColor] src.wires |= wireFlag switch(wireIndex) if(WIRE_SHOCK) @@ -347,7 +370,7 @@ switch(wireIndex) if(WIRE_SHOCK) src.seconds_electrified = 30 - if (WIRE_SHOOTINV) + if(WIRE_SHOOTINV) src.shoot_inventory = !src.shoot_inventory if(WIRE_SCANID) src.locked = -1 @@ -385,80 +408,23 @@ return 1 /obj/machinery/smartfridge/proc/shock(mob/user, prb) - if(!src.ispowered) // unpowered, no shock - return 0 - if(!prob(prb)) - return 0 + if(!ispowered) return 0 + if(!prob(prb)) return 0 + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, src) s.start() - if (electrocute_mob(user, get_area(src), src, 0.7)) - return 1 - else - return 0 + + return electrocute_mob(user, get_area(src), src, 0.7) /************************ * Secure SmartFridges *************************/ /obj/machinery/smartfridge/secure/Topic(href, href_list) - usr.set_machine(src) - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) - if ((!src.allowed(usr)) && (!src.emagged) && (src.locked != -1) && href_list["vend"]) //For SECURE VENDING MACHINES YEAH - usr << "\red Access denied." //Unless emagged of course - return - ..() - return - -/obj/machinery/smartfridge/secure/interact(mob/user as mob) - - if(!src.ispowered) - return - - var/dat = "Select an item:
" - - if (contents.len == 0) - dat += "No product loaded!" - else - for (var/O in item_quants) - if(item_quants[O] > 0) - var/N = item_quants[O] - dat += "[capitalize(O)]:" - dat += " [N] " - dat += "Vend " - if(N > 5) - dat += "(x5)" - if(N > 10) - dat += "(x10)" - if(N > 25) - dat += "(x25)" - if(N > 1) - dat += "(All)" - dat += "
" - - dat += "
" - if(panel_open) - var/list/vendwires = list( - "Violet" = 1, - "Orange" = 2, - "Green" = 3 - ) - dat += "


Access Panel
" - for(var/wiredesc in vendwires) - var/is_uncut = src.wires & APCWireColorToFlag[vendwires[wiredesc]] - dat += "[wiredesc] wire: " - if(!is_uncut) - dat += "Mend" - else - dat += "Cut " - dat += "Pulse " - dat += "
" - - dat += "
" - dat += "The orange light is [(src.seconds_electrified == 0) ? "off" : "on"].
" - //dat += "The red light is [src.shoot_inventory ? "off" : "blinking"].
" - dat += "The green light is [src.locked == 1 ? "off" : "[src.locked == -1 ? "blinking" : "on"]"].
" - user << browse("[src] Supplies[dat]", "window=smartfridge") - return - -//TODO: Make smartfridges hackable. - JoeyJo0 + if(!ispowered) return 0 + if (usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) + if (!allowed(usr) && !emagged && locked != -1 && href_list["vend"]) + usr << "\red Access denied." + return 0 + return ..() diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index a9b7183f..8a0d61b5 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -174,7 +174,7 @@ Class Procs: return 1 if ( ! (istype(usr, /mob/living/carbon/human) || \ istype(usr, /mob/living/silicon) || \ - istype(usr, /mob/living/carbon/monkey) && ticker && ticker.mode.name == "monkey") ) + istype(usr, /mob/living/carbon/monkey)) ) usr << "\red You don't have the dexterity to do this!" return 1 @@ -216,7 +216,7 @@ Class Procs: return 1 if ( ! (istype(usr, /mob/living/carbon/human) || \ istype(usr, /mob/living/silicon) || \ - istype(usr, /mob/living/carbon/monkey) && ticker && ticker.mode.name == "monkey") ) + istype(usr, /mob/living/carbon/monkey)) ) usr << "\red You don't have the dexterity to do this!" return 1 /* @@ -248,3 +248,13 @@ Class Procs: uid = gl_uid gl_uid++ +/obj/machinery/proc/state(var/msg) + for(var/mob/O in hearers(src, null)) + O.show_message("\icon[src] [msg]", 2) + +/obj/machinery/proc/ping(text=null) + if (!text) + text = "\The [src] pings." + + state(text, "blue") + playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index 048e273f..1ca95c1b 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -27,6 +27,9 @@ Buildable meters #define PIPE_UP 21 #define PIPE_DOWN 22 ///// Z-Level stuff +#define PIPE_GAS_FILTER_M 23 +#define PIPE_GAS_MIXER_T 24 +#define PIPE_GAS_MIXER_M 25 /obj/item/pipe name = "pipe" @@ -71,6 +74,12 @@ Buildable meters src.pipe_type = PIPE_MVALVE else if(istype(make_from, /obj/machinery/atmospherics/binary/pump)) src.pipe_type = PIPE_PUMP + else if(istype(make_from, /obj/machinery/atmospherics/trinary/filter/m_filter)) + src.pipe_type = PIPE_GAS_FILTER_M + else if(istype(make_from, /obj/machinery/atmospherics/trinary/mixer/t_mixer)) + src.pipe_type = PIPE_GAS_MIXER_T + else if(istype(make_from, /obj/machinery/atmospherics/trinary/mixer/m_mixer)) + src.pipe_type = PIPE_GAS_MIXER_M else if(istype(make_from, /obj/machinery/atmospherics/trinary/filter)) src.pipe_type = PIPE_GAS_FILTER else if(istype(make_from, /obj/machinery/atmospherics/trinary/mixer)) @@ -132,6 +141,9 @@ Buildable meters "pipe up", \ "pipe down", \ ///// Z-Level stuff + "gas filter m", \ + "gas mixer t", \ + "gas mixer m", \ ) name = nlist[pipe_type+1] + " fitting" var/list/islist = list( \ @@ -160,6 +172,9 @@ Buildable meters "cap", \ "cap", \ ///// Z-Level stuff + "m_filter", \ + "t_mixer", \ + "m_mixer", \ ) icon_state = islist[pipe_type + 1] @@ -230,6 +245,10 @@ Buildable meters return flip|cw|acw if(PIPE_GAS_FILTER, PIPE_GAS_MIXER,PIPE_MTVALVE) return dir|flip|cw + if(PIPE_GAS_FILTER_M, PIPE_GAS_MIXER_M) + return dir|flip|acw + if(PIPE_GAS_MIXER_T) + return dir|cw|acw if(PIPE_CAP) return flip ///// Z-Level stuff @@ -490,7 +509,7 @@ Buildable meters P.node3.initialize() P.node3.build_network() - if(PIPE_GAS_MIXER) //gas filter + if(PIPE_GAS_MIXER) //gas mixer var/obj/machinery/atmospherics/trinary/mixer/P = new(src.loc) P.dir = dir P.initialize_directions = pipe_dir @@ -510,6 +529,66 @@ Buildable meters P.node3.initialize() P.node3.build_network() + if(PIPE_GAS_FILTER_M) //gas filter mirrored + var/obj/machinery/atmospherics/trinary/filter/m_filter/P = new(src.loc) + P.dir = dir + P.initialize_directions = pipe_dir + if (pipename) + P.name = pipename + var/turf/T = P.loc + P.level = T.intact ? 2 : 1 + P.initialize() + P.build_network() + if (P.node1) + P.node1.initialize() + P.node1.build_network() + if (P.node2) + P.node2.initialize() + P.node2.build_network() + if (P.node3) + P.node3.initialize() + P.node3.build_network() + + if(PIPE_GAS_MIXER_T) //gas mixer-t + var/obj/machinery/atmospherics/trinary/mixer/t_mixer/P = new(src.loc) + P.dir = dir + P.initialize_directions = pipe_dir + if (pipename) + P.name = pipename + var/turf/T = P.loc + P.level = T.intact ? 2 : 1 + P.initialize() + P.build_network() + if (P.node1) + P.node1.initialize() + P.node1.build_network() + if (P.node2) + P.node2.initialize() + P.node2.build_network() + if (P.node3) + P.node3.initialize() + P.node3.build_network() + + if(PIPE_GAS_MIXER_M) //gas mixer mirrored + var/obj/machinery/atmospherics/trinary/mixer/m_mixer/P = new(src.loc) + P.dir = dir + P.initialize_directions = pipe_dir + if (pipename) + P.name = pipename + var/turf/T = P.loc + P.level = T.intact ? 2 : 1 + P.initialize() + P.build_network() + if (P.node1) + P.node1.initialize() + P.node1.build_network() + if (P.node2) + P.node2.initialize() + P.node2.build_network() + if (P.node3) + P.node3.initialize() + P.node3.build_network() + if(PIPE_SCRUBBER) //scrubber var/obj/machinery/atmospherics/unary/vent_scrubber/S = new(src.loc) S.dir = dir @@ -709,4 +788,7 @@ Buildable meters #undef PIPE_VOLUME_PUMP #undef PIPE_OUTLET_INJECT #undef PIPE_MTVALVE +#undef PIPE_GAS_FILTER_M +#undef PIPE_GAS_MIXER_T +#undef PIPE_GAS_MIXER_M //#undef PIPE_MANIFOLD4W diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm index bbbe4e20..0db01901 100644 --- a/code/game/machinery/pipe/pipe_dispenser.dm +++ b/code/game/machinery/pipe/pipe_dispenser.dm @@ -34,7 +34,10 @@ Scrubber
Meter
Gas Filter
+Gas Filter-Mirrored
Gas Mixer
+Gas Mixer-Mirrored
+Gas Mixer-T
Heat exchange:
Pipe
Bent Pipe
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 94b8ac1d..830ff05a 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -59,7 +59,9 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept signal.data["vmask"], signal.data["vmessage"], signal.data["radio"], signal.data["message"], signal.data["name"], signal.data["job"], - signal.data["realname"], signal.data["vname"],, signal.data["compression"], signal.data["level"], signal.frequency) + signal.data["realname"], signal.data["vname"],, + signal.data["compression"], signal.data["level"], signal.frequency, + signal.data["verb"], signal.data["language"] ) /** #### - Simple Broadcast - #### **/ @@ -84,7 +86,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept signal.data["vmask"], signal.data["vmessage"], signal.data["radio"], signal.data["message"], signal.data["name"], signal.data["job"], - signal.data["realname"], signal.data["vname"], 4, signal.data["compression"], signal.data["level"], signal.frequency) + signal.data["realname"], signal.data["vname"], 4, signal.data["compression"], signal.data["level"], signal.frequency, + signal.data["verb"], signal.data["language"]) if(!message_delay) message_delay = 1 @@ -147,14 +150,16 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept signal.data["vmask"], signal.data["vmessage"], signal.data["radio"], signal.data["message"], signal.data["name"], signal.data["job"], - signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency) + signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency, + signal.data["verb"], signal.data["language"]) else if(intercept) Broadcast_Message(signal.data["connection"], signal.data["mob"], signal.data["vmask"], signal.data["vmessage"], signal.data["radio"], signal.data["message"], signal.data["name"], signal.data["job"], - signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency) + signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency, + signal.data["verb"], signal.data["language"]) @@ -218,7 +223,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept /proc/Broadcast_Message(var/datum/radio_frequency/connection, var/mob/M, var/vmask, var/vmessage, var/obj/item/device/radio/radio, var/message, var/name, var/job, var/realname, var/vname, - var/data, var/compression, var/list/level, var/freq) + var/data, var/compression, var/list/level, var/freq, var/verbage = "says", var/datum/language/speaking = null) + /* ###### Prepare the radio connection ###### */ @@ -371,7 +377,6 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept // syndies! if (display_freq == SYND_FREQ) part_a = "" - // centcomm channels (deathsquid and ert) else if (display_freq in CENT_FREQS) part_a = "" @@ -445,102 +450,40 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept //End of research and feedback code. - var/aitrack = "" - /* ###### Send the message ###### */ /* --- Process all the mobs that heard a masked voice (understood) --- */ if (length(heard_masked)) - var/N = name - var/J = job - var/rendered = "[part_a][N][part_b][quotedmsg][part_c]" for (var/mob/R in heard_masked) - aitrack = "" - if(data == 4) - aitrack = "" - - if(istype(R, /mob/living/silicon/ai)) - R.show_message("[part_a][aitrack][N] ([J]) [part_b][quotedmsg][part_c]", 2) - else - R.show_message(rendered, 2) + R.hear_radio(message,verbage, speaking, part_a, part_b, M, 0, name) /* --- Process all the mobs that heard the voice normally (understood) --- */ if (length(heard_normal)) - var/rendered = "[part_a][realname][part_b][quotedmsg][part_c]" - for (var/mob/R in heard_normal) - aitrack = "" - if(data == 4) - aitrack = "" - - if(istype(R, /mob/living/silicon/ai)) - R.show_message("[part_a][aitrack][realname] ([job]) [part_b][quotedmsg][part_c]", 2) - else - R.show_message(rendered, 2) + R.hear_radio(message, verbage, speaking, part_a, part_b, M, 0, realname) /* --- Process all the mobs that heard the voice normally (did not understand) --- */ if (length(heard_voice)) - var/rendered = "[part_a][vname][part_b][vmessage][part_c]" - for (var/mob/R in heard_voice) - aitrack = "" - if(data == 4) - aitrack = "" - - - if(istype(R, /mob/living/silicon/ai)) - R.show_message("[part_a][aitrack][vname] ([job]) [part_b][vmessage]][part_c]", 2) - else - R.show_message(rendered, 2) + R.hear_radio(message,verbage, speaking, part_a, part_b, M,0, vname) /* --- Process all the mobs that heard a garbled voice (did not understand) --- */ // Displays garbled message (ie "f*c* **u, **i*er!") if (length(heard_garbled)) - if(M) - quotedmsg = M.say_quote(stars(message)) - else - quotedmsg = stars(quotedmsg) - - var/rendered = "[part_a][vname][part_b][quotedmsg][part_c]" - for (var/mob/R in heard_garbled) - aitrack = "" - if(data == 4) - aitrack = "" - - - if(istype(R, /mob/living/silicon/ai)) - R.show_message("[part_a][aitrack][vname][part_b][quotedmsg][part_c]", 2) - else - R.show_message(rendered, 2) + R.hear_radio(message, verbage, speaking, part_a, part_b, M, 1, vname) /* --- Complete gibberish. Usually happens when there's a compressed message --- */ if (length(heard_gibberish)) - if(M) - quotedmsg = M.say_quote(Gibberish(message, compression + 50)) - else - quotedmsg = Gibberish(quotedmsg, compression + 50) - - var/rendered = "[part_a][Gibberish(name, compression + 50)][part_b][quotedmsg][part_c]" - for (var/mob/R in heard_gibberish) - aitrack = "" - if(data == 4) - aitrack = "" - - - if(istype(R, /mob/living/silicon/ai)) - R.show_message("[part_a][aitrack][Gibberish(realname, compression + 50)] ([Gibberish(job, compression + 50)]) [part_b][quotedmsg][part_c]", 2) - else - R.show_message(rendered, 2) - + R.hear_radio(message, verbage, speaking, part_a, part_b, M, 1) /proc/Broadcast_SimpleMessage(var/source, var/frequency, var/text, var/data, var/mob/M, var/compression, var/level) diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index efee4d39..ff955640 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -91,7 +91,9 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() "type" = signal.data["type"], "server" = signal.data["server"], "reject" = signal.data["reject"], - "level" = signal.data["level"] + "level" = signal.data["level"], + "verb" = signal.data["verb"], + "language" = signal.data["language"] ) // Keep the "original" signal constant diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index cef7571c..8b72ab19 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -53,6 +53,8 @@ var/const/WIRE_SHOOTINV = 4 var/check_accounts = 0 // 1 = requires PIN and checks accounts. 0 = You slide an ID, it vends, SPACE COMMUNISM! + var/obj/item/weapon/spacecash/ewallet/ewallet + /obj/machinery/vending/New() ..() @@ -150,6 +152,11 @@ else if(istype(W, /obj/item/weapon/card) && currently_vending) var/obj/item/weapon/card/I = W scan_card(I) + else if (istype(W, /obj/item/weapon/spacecash/ewallet)) + user.drop_item() + W.loc = src + ewallet = W + user << "\blue You insert the [W] into the [src]" else if(src.panel_open) @@ -243,7 +250,10 @@ dat += "Select an item:

" //the rest is just general spacing and bolding if (premium.len > 0) - dat += "Coin slot: [coin ? coin : "No coin inserted"] (Remove)

" + dat += "Coin slot: [coin ? coin : "No coin inserted"] (Remove)
" + + if (ewallet) + dat += "Charge card's credits: [ewallet ? ewallet.worth : "No charge card inserted"] (Remove)

" if (src.product_records.len == 0) dat += "No product loaded!" @@ -317,6 +327,15 @@ usr << "\blue You remove the [coin] from the [src]" coin = null + if(href_list["remove_ewallet"] && !istype(usr,/mob/living/silicon)) + if (!ewallet) + usr << "There is no charge card in this machine." + return + ewallet.loc = src.loc + if(!usr.get_active_hand()) + usr.put_in_hands(ewallet) + usr << "\blue You remove the [ewallet] from the [src]" + ewallet = null if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) usr.set_machine(src) @@ -344,9 +363,17 @@ if(R.price == null) src.vend(R, usr) else - src.currently_vending = R - src.updateUsrDialog() - + if (ewallet) + if (R.price <= ewallet.worth) + ewallet.worth -= R.price + src.vend(R, usr) + else + usr << "\red The ewallet doesn't have enough money to pay for that." + src.currently_vending = R + src.updateUsrDialog() + else + src.currently_vending = R + src.updateUsrDialog() return else if (href_list["cancel_buying"]) @@ -686,7 +713,7 @@ icon_state = "cart" icon_deny = "cart-deny" products = list(/obj/item/weapon/cartridge/medical = 10,/obj/item/weapon/cartridge/engineering = 10,/obj/item/weapon/cartridge/security = 10, - /obj/item/weapon/cartridge/janitor = 10,/obj/item/weapon/cartridge/signal/toxins = 10,/obj/item/device/pda/heads = 10, + /obj/item/weapon/cartridge/janitor = 10,/obj/item/weapon/cartridge/signal/science = 10,/obj/item/device/pda/heads = 10, /obj/item/weapon/cartridge/captain = 3,/obj/item/weapon/cartridge/quartermaster = 10) @@ -766,7 +793,7 @@ product_ads = "We like plants!;Don't you want some?;The greenest thumbs ever.;We like big plants.;Soft soil..." icon_state = "nutri" icon_deny = "nutri-deny" - products = list(/obj/item/beezeez = 45,/obj/item/nutrient/ez = 35,/obj/item/nutrient/l4z = 25,/obj/item/nutrient/rh = 15,/obj/item/weapon/pestspray = 20, + products = list(/obj/item/nutrient/ez = 35,/obj/item/nutrient/l4z = 25,/obj/item/nutrient/rh = 15,/obj/item/weapon/pestspray = 20, /obj/item/weapon/reagent_containers/syringe = 5,/obj/item/weapon/storage/bag/plants = 5) premium = list(/obj/item/weapon/reagent_containers/glass/bottle/ammonia = 10,/obj/item/weapon/reagent_containers/glass/bottle/diethylamine = 5) @@ -779,7 +806,7 @@ products = list(/obj/item/seeds/bananaseed = 3,/obj/item/seeds/berryseed = 3,/obj/item/seeds/carrotseed = 3,/obj/item/seeds/chantermycelium = 3,/obj/item/seeds/chiliseed = 3, /obj/item/seeds/cornseed = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/potatoseed = 3, /obj/item/seeds/replicapod = 3,/obj/item/seeds/soyaseed = 3, /obj/item/seeds/sunflowerseed = 3,/obj/item/seeds/tomatoseed = 3,/obj/item/seeds/towermycelium = 3,/obj/item/seeds/wheatseed = 3,/obj/item/seeds/appleseed = 3, - /obj/item/seeds/poppyseed = 3,/obj/item/seeds/ambrosiavulgarisseed = 3,/obj/item/seeds/whitebeetseed = 3,/obj/item/seeds/watermelonseed = 3,/obj/item/seeds/limeseed = 3, + /obj/item/seeds/poppyseed = 3,/obj/item/seeds/sugarcaneseed = 3,/obj/item/seeds/ambrosiavulgarisseed = 3,/obj/item/seeds/whitebeetseed = 3,/obj/item/seeds/watermelonseed = 3,/obj/item/seeds/limeseed = 3, /obj/item/seeds/lemonseed = 3,/obj/item/seeds/orangeseed = 3,/obj/item/seeds/grassseed = 3,/obj/item/seeds/cocoapodseed = 3,/obj/item/seeds/plumpmycelium = 2, /obj/item/seeds/cabbageseed = 3,/obj/item/seeds/grapeseed = 3,/obj/item/seeds/pumpkinseed = 3,/obj/item/seeds/cherryseed = 3,/obj/item/seeds/plastiseed = 3,/obj/item/seeds/riceseed = 3) contraband = list(/obj/item/seeds/amanitamycelium = 2,/obj/item/seeds/glowshroom = 2,/obj/item/seeds/libertymycelium = 2,/obj/item/seeds/mtearseed = 2, diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 3cbdf043..dc821839 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -11,13 +11,10 @@ var/fire_volume = 50 //How loud it is played. var/auto_rearm = 0 //Does the weapon reload itself after each shot? -/obj/item/mecha_parts/mecha_equipment/weapon/can_attach(var/obj/mecha/combat/M) - - if(istype(M)) - return ..() - else +/obj/item/mecha_parts/mecha_equipment/weapon/can_attach(var/obj/mecha/combat/M as obj) + if(!istype(M)) return 0 - + return ..() /obj/item/mecha_parts/mecha_equipment/weapon/action_checks(atom/target) if(projectiles <= 0) diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 4a27f4e4..8c87a0d8 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -376,6 +376,11 @@ /obj/machinery/mecha_part_fabricator/proc/build_part(var/obj/item/part) if(!part) return + + // critical exploit prevention, do not remove unless you replace it -walter0o + if( !(locate(part, src.contents)) || !(part.vars.Find("construction_time")) || !(part.vars.Find("construction_cost")) ) // these 3 are the current requirements for an object being buildable by the mech_fabricator + return + src.being_built = new part.type(src) src.desc = "It's building [src.being_built]." src.remove_resources(part) @@ -617,9 +622,26 @@ onclose(user, "mecha_fabricator") return +/obj/machinery/mecha_part_fabricator/proc/exploit_prevention(var/obj/Part, mob/user as mob, var/desc_exploit) +// critical exploit prevention, feel free to improve or replace this, but do not remove it -walter0o + + if(!Part || !user || !istype(Part) || !istype(user)) // sanity + return 1 + + if( !(locate(Part, src.contents)) || !(Part.vars.Find("construction_time")) || !(Part.vars.Find("construction_cost")) ) // these 3 are the current requirements for an object being buildable by the mech_fabricator + + var/turf/LOC = get_turf(user) + message_admins("[key_name_admin(user)] tried to exploit an Exosuit Fabricator to [desc_exploit ? "get the desc of" : "duplicate"] [Part] ! ([LOC ? "JMP" : "null"])", 0) + log_admin("EXPLOIT : [key_name(user)] tried to exploit an Exosuit Fabricator to [desc_exploit ? "get the desc of" : "duplicate"] [Part] !") + return 1 + + return null /obj/machinery/mecha_part_fabricator/Topic(href, href_list) - ..() + + if(..()) // critical exploit prevention, do not remove unless you replace it -walter0o + return + var/datum/topic_input/filter = new /datum/topic_input(href,href_list) if(href_list["part_set"]) var/tpart_set = filter.getStr("part_set") @@ -630,13 +652,25 @@ src.part_set = tpart_set screen = "parts" if(href_list["part"]) - var/list/part = filter.getObj("part") + var/obj/part = filter.getObj("part") + + // critical exploit prevention, do not remove unless you replace it -walter0o + if(src.exploit_prevention(part, usr)) + return + if(!processing_queue) build_part(part) else add_to_queue(part) if(href_list["add_to_queue"]) - add_to_queue(filter.getObj("add_to_queue")) + var/obj/part = filter.getObj("add_to_queue") + + // critical exploit prevention, do not remove unless you replace it -walter0o + if(src.exploit_prevention(part, usr)) + return + + add_to_queue(part) + return update_queue_on_page() if(href_list["remove_from_queue"]) remove_from_queue(filter.getNum("remove_from_queue")) @@ -675,7 +709,12 @@ return update_queue_on_page() if(href_list["part_desc"]) var/obj/part = filter.getObj("part_desc") - if(part) + + // critical exploit prevention, do not remove unless you replace it -walter0o + if(src.exploit_prevention(part, usr, 1)) + return + + if(part) temp = {"

[part] description:

[part.desc]
Return diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm index 6fa5b217..ed460aff 100644 --- a/code/game/mecha/mecha_construction_paths.dm +++ b/code/game/mecha/mecha_construction_paths.dm @@ -586,7 +586,7 @@ const_holder.density = 1 spawn() del src - return 0 + return /datum/construction/reversible/mecha/firefighter @@ -888,7 +888,7 @@ const_holder.density = 1 spawn() del src - return 0 + return /datum/construction/reversible/mecha/durand result = "/obj/mecha/combat/durand" diff --git a/code/game/objects/closets/secure/research.dm b/code/game/objects/closets/secure/research.dm index 46b64572..dc4081a3 100644 --- a/code/game/objects/closets/secure/research.dm +++ b/code/game/objects/closets/secure/research.dm @@ -16,7 +16,7 @@ var/obj/item/weapon/storage/backpack/BPK = new /obj/item/weapon/storage/backpack(src) var/obj/item/weapon/storage/box/B = new(BPK) new /obj/item/weapon/pen(B) - new /obj/item/device/pda/toxins(src) + new /obj/item/device/pda/science(src) new /obj/item/weapon/tank/oxygen(src) new /obj/item/clothing/mask/gas(src) new /obj/item/device/radio/headset/headset_sci(src) diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm index 9c5e19c8..25edeb2d 100644 --- a/code/game/objects/effects/aliens.dm +++ b/code/game/objects/effects/aliens.dm @@ -184,6 +184,7 @@ anchored = 1 density = 0 + layer = 2 var/health = 15 var/obj/effect/alien/weeds/node/linked_node = null @@ -191,6 +192,7 @@ icon_state = "weednode" name = "purple sac" desc = "Weird purple octopus-like thing." + layer = 3 luminosity = NODERANGE var/node_range = NODERANGE @@ -200,10 +202,10 @@ /obj/effect/alien/weeds/New(pos, node) ..() - linked_node = node if(istype(loc, /turf/space)) del(src) return + linked_node = node if(icon_state == "weeds")icon_state = pick("weeds", "weeds1", "weeds2") spawn(rand(150, 200)) if(src) @@ -230,6 +232,9 @@ Alien plants should do something if theres a lot of poison del(src) return + if(!linked_node || (get_dist(linked_node, src) > linked_node.node_range) ) + return + direction_loop: for(var/dirn in cardinal) var/turf/T = get_step(src, dirn) @@ -237,9 +242,6 @@ Alien plants should do something if theres a lot of poison if (!istype(T) || T.density || locate(/obj/effect/alien/weeds) in T || istype(T.loc, /area/arrival) || istype(T, /turf/space)) continue - if(!linked_node || get_dist(linked_node, src) > linked_node.node_range) - return - // if (locate(/obj/movable, T)) // don't propogate into movables // continue diff --git a/code/game/objects/effects/decals/Cleanable/fuel.dm b/code/game/objects/effects/decals/Cleanable/fuel.dm index 5cc3ebd3..f3faa7ed 100644 --- a/code/game/objects/effects/decals/Cleanable/fuel.dm +++ b/code/game/objects/effects/decals/Cleanable/fuel.dm @@ -21,7 +21,7 @@ obj/effect/decal/cleanable/liquid_fuel proc/Spread() //Allows liquid fuels to sometimes flow into other tiles. - if(amount < 0.5) return + if(amount < 5.0) return var/turf/simulated/S = loc if(!istype(S)) return for(var/d in cardinal) diff --git a/code/game/objects/effects/decals/posters/bs12.dm b/code/game/objects/effects/decals/posters/bs12.dm index 3d6261fb..6047eaa9 100644 --- a/code/game/objects/effects/decals/posters/bs12.dm +++ b/code/game/objects/effects/decals/posters/bs12.dm @@ -143,3 +143,104 @@ icon_state="bsposter29" name = "Winter Is Coming" desc = "On the poster is a frighteningly large wolf, he warns: \"Only YOU can keep the station from freezing during planetary occultation!\"" + +/datum/poster/bay_30 + icon_state="bsposter30" + name = "Ambrosia Vulgaris" + desc = "Just looking at this poster makes you feel a little bit dizzy." + +/datum/poster/bay_31 + icon_state="bsposter31" + name = "Donut Corp" + desc = "This is an advertisement for Donut Corp, the new innovation in donut technology!" + +/datum/poster/bay_32 + icon_state="bsposter32" + name = "Eat!" + desc = "A poster depicting a hamburger. The poster orders you to consume the hamburger." + +/datum/poster/bay_33 + icon_state="bsposter33" + name = "Tools, tools, tools" + desc = "You can never have enough tools, thats for sure!" + +/datum/poster/bay_34 + icon_state="bsposter34" + name = "Power Up!" + desc = "High reward, higher risk!" + +/datum/poster/bay_35 + icon_state="bsposter35" + name = "Lamarr" + desc = "This is a poster depicting the pet and mascot of the NSS Exodus science department." + +/datum/poster/bay_36 + icon_state="bsposter36" + name = "Fancy Borg" + desc = "A poster depicting a cyborg using the service module. 'Fancy Borg' is written on it." + +/datum/poster/bay_37 + icon_state="bsposter37" + name = "Fancier Borg" + desc = "A poster depicting a cyborg using the service module. 'Fancy Borg' is written on it. This is even fancier than the first poster." + +/datum/poster/bay_38 + icon_state="bsposter38" + name = "Toaster Love" + desc = "This is a poster of a toaster containing two slices of bread. The word LOVE is written in big pink letters underneath." + +/datum/poster/bay_39 + icon_state="bsposter39" + name = "Responsible medbay habits, No #91" + desc = "A safety poster with a chemist holding a vial. \"Always wear safety gear while handling dangerous chemicals, even if it concerns only small amounts.\"" + +/datum/poster/bay_40 + icon_state="bsposter40" + name = "Agreeable work environment" + desc = "This poster depicts a young woman in a stylish dress. \"Try to aim for a pleasant atmosphere in the workspace. A friendly word can do more than forms in triplicate.\"" + +/datum/poster/bay_41 + icon_state="bsposter41" + name = "Professional work environment" + desc = "A safety poster featuring a green haired woman in a shimmering blue dress. \"As an Internal Affairs Agent, your job is to create a fair and agreeable work environment for the crewmembers, as discreetly and professionally as possible.\"" + +/datum/poster/bay_42 + icon_state="bsposter42" + name = "Engineering pinup" + desc = "This is pin-up poster. A half-naked girl with white hair, toned muscles and stunning blue eyes looks back at you from the poster. Her welding helmet, tattoos and grey jumpsuit hanging around her waist gives a bit of a rugged feel." + +/datum/poster/bay_43 + icon_state="bsposter43" + name = "Responsible medbay habits, No #3" + desc = "A safety poster with a purple-haired surgeon. She looks a bit cross. \"Let the surgeons do their work. NEVER replace or remove a surgery tool from where the surgeon put it.\"" + +/datum/poster/bay_44 + icon_state="bsposter44" + name = "Time for a drink?" + desc = "This poster depicts a friendly-looking Tajara holding a tray of drinks." + +/datum/poster/bay_45 + icon_state="bsposter45" + name = "Responsible engineering habits, No #1" + desc = "A safety poster featuring a blue haired engineer. \"When repairing a machine or construction, always aim for long-term solutions.\"" + +/datum/poster/bay_46 + icon_state="bsposter46" + name = "Inspirational lawyer" + desc = "An inspirational poster depicting a Skrellian lawyer. He seems to be shouting something, while pointing fiercely to the right." + +/datum/poster/bay_47 + icon_state="bsposter47" + name = "Security pinup" + desc = "This is a pin-up poster. A dark skinned white haired girl poses in the sunlight wearing a tank top with her stomach exposed. The text on the poster states \"M, Succubus of Security.\" and a lipstick mark stains the top right corner, as if kissed by the model herself." + + /datum/poster/bay_48 + icon_state="bsposter48" + name = "Borg pinup?" + desc = "This is a.. pin-up poster? It is a diagram on an old model of cyborg with a note scribbled in marker on the bottom, on the top there is a large XO written in red marker." + + /datum/poster/bay_49 + icon_state="bsposter49" + name = "Engineering recruitment" + desc = "This is a poster showing an engineer relaxing by a computer, the text states \"Living the life! Join Engineering today!\"" + diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 762912c2..7c92b737 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -26,9 +26,37 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa epicenter = get_turf(epicenter) if(!epicenter) return + var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flash_range) + //playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(devastation_range*2,1) ) + //playsound(epicenter, "explosion", 100, 1, round(devastation_range,1) ) - playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(devastation_range*2,1) ) - playsound(epicenter, "explosion", 100, 1, round(devastation_range,1) ) +// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves. + +// Stereo users will also hear the direction of the explosion! + +// Calculate far explosion sound range. Only allow the sound effect for heavy/devastating explosions. + +// 3/7/14 will calculate to 80 + 35 + var/far_dist = 0 + far_dist += heavy_impact_range * 5 + far_dist += devastation_range * 20 + var/frequency = get_rand_frequency() + for(var/mob/M in player_list) + // Double check for client + if(M && M.client) + var/turf/M_turf = get_turf(M) + if(M_turf && M_turf.z == epicenter.z) + var/dist = get_dist(M_turf, epicenter) + // If inside the blast radius + world.view - 2 + if(dist <= round(max_range + world.view - 2, 1)) + M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound + + //You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station. + + else if(dist <= far_dist) + var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist + far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion + M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5) var/close = range(world.view+round(devastation_range,1), epicenter) // to all distanced mobs play a different sound @@ -55,7 +83,7 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa var/y0 = epicenter.y var/z0 = epicenter.z - for(var/turf/T in range(epicenter, max(devastation_range, heavy_impact_range, light_impact_range))) + for(var/turf/T in range(epicenter, max_range)) var/dist = cheap_pythag(T.x - x0,T.y - y0) if(dist < devastation_range) dist = 1 diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 4639aae0..808640a4 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -210,6 +210,7 @@ /obj/item/proc/moved(mob/user as mob, old_loc as turf) return +// apparently called whenever an item is removed from a slot, container, or anything else. /obj/item/proc/dropped(mob/user as mob) ..() @@ -237,18 +238,6 @@ /obj/item/proc/equipped(var/mob/user, var/slot) return -//returns 1 if the item is equipped by a mob, 0 otherwise. -//This might need some error trapping, not sure if get_equipped_items() is safe for non-human mobs. -/obj/item/proc/is_equipped() - if(!ismob(loc)) - return 0 - - var/mob/M = loc - if(src in M.get_equipped_items()) - return 1 - else - return 0 - //the mob M is attempting to equip this item into the slot passed through as 'slot'. Return 1 if it can do this and 0 if it can't. //If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen. //Set disable_warning to 1 if you wish it to not give you outputs. diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index d3528ac6..ee96da71 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -5,6 +5,7 @@ desc = "A folded bag designed for the storage and transportation of cadavers." icon = 'icons/obj/bodybag.dmi' icon_state = "bodybag_folded" + w_class = 2.0 attack_self(mob/user) var/obj/structure/closet/body_bag/R = new /obj/structure/closet/body_bag(user.loc) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index eefac288..1af5587f 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -10,7 +10,7 @@ var/global/list/obj/item/device/pda/PDAs = list() icon = 'icons/obj/pda.dmi' icon_state = "pda" item_state = "electronic" - w_class = 1.0 + w_class = 2.0 flags = FPRINT | TABLEPASS slot_flags = SLOT_ID | SLOT_BELT @@ -83,8 +83,8 @@ var/global/list/obj/item/device/pda/PDAs = list() icon_state = "pda-j" ttone = "slip" -/obj/item/device/pda/toxins - default_cartridge = /obj/item/weapon/cartridge/signal/toxins +/obj/item/device/pda/science + default_cartridge = /obj/item/weapon/cartridge/signal/science icon_state = "pda-tox" ttone = "boom" @@ -338,7 +338,7 @@ var/global/list/obj/item/device/pda/PDAs = list() return lastmode = mode - + var/title = "Personal Data Assistant" var/data[0] // This is the data that will be sent to the PDA @@ -367,7 +367,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(mode in cartmodes) data["records"] = cartridge.create_NanoUI_values() - if(mode == 0) + if(mode == 0) cartdata["name"] = cartridge.name cartdata["access"] = list(\ "access_security" = cartridge.access_security,\ @@ -556,7 +556,7 @@ var/global/list/obj/item/device/pda/PDAs = list() mode = 1 if("2")//Messenger mode = 2 - if("21")//Read messeges + if("21")//Read messages mode = 21 if("3")//Atmos scan mode = 3 @@ -818,7 +818,7 @@ var/global/list/obj/item/device/pda/PDAs = list() message += "You feel a searing heat! Your [P] is burning!" if(i>=20 && i<=25) //EMP empulse(P.loc, 3, 6, 1) - message += "Your [P] emits a wave of electomagnetic energy!" + message += "Your [P] emits a wave of electromagnetic energy!" if(i>=25 && i<=40) //Smoke var/datum/effect/effect/system/smoke_spread/chem/S = new /datum/effect/effect/system/smoke_spread/chem S.attach(P.loc) @@ -895,7 +895,7 @@ var/global/list/obj/item/device/pda/PDAs = list() var/obj/machinery/message_server/useMS = null if(message_servers) for (var/obj/machinery/message_server/MS in message_servers) - //PDAs are now dependant on the Message Server. + //PDAs are now dependent on the Message Server. if(MS.active) useMS = MS break @@ -914,7 +914,7 @@ var/global/list/obj/item/device/pda/PDAs = list() t = Gibberish(t, signal.data["compression"] + 50) if(useMS && useTC) // only send the message if it's stable - if(useTC != 2) // Does our recepient have a broadcaster on their level? + if(useTC != 2) // Does our recipient have a broadcaster on their level? U << "ERROR: Cannot reach recipient." return useMS.send_pda_message("[P.owner]","[owner]","[t]") @@ -957,7 +957,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(L) L << "\icon[P] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)" - nanomanager.update_user_uis(L, P) // Update the recieving user's PDA UI so that they can see the new message + nanomanager.update_user_uis(L, P) // Update the receiving user's PDA UI so that they can see the new message nanomanager.update_user_uis(U, P) // Update the sending user's PDA UI so that they can see the new message @@ -1293,7 +1293,7 @@ var/global/list/obj/item/device/pda/PDAs = list() var/newcart = pick( /obj/item/weapon/cartridge/engineering, /obj/item/weapon/cartridge/security, /obj/item/weapon/cartridge/medical, - /obj/item/weapon/cartridge/signal/toxins, + /obj/item/weapon/cartridge/signal/science, /obj/item/weapon/cartridge/quartermaster) new newcart(src) diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index 090ed8dc..d0bc984a 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -103,7 +103,7 @@ name = "generic signaler cartridge" desc = "A data cartridge with an integrated radio signaler module." -/obj/item/weapon/cartridge/signal/toxins +/obj/item/weapon/cartridge/signal/science name = "Signal Ace 2" desc = "Complete with integrated radio signaler!" icon_state = "cart-tox" diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 4bf9c2c8..13641608 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -107,6 +107,7 @@ item_state = "" flags = FPRINT | TABLEPASS | CONDUCT brightness_on = 2 + w_class = 1 /obj/item/device/flashlight/heavy name = "heavy duty flashlight" @@ -279,3 +280,25 @@ var/charge_tick = 0 return // This code... Gave me cancer... -Dalekfodder + +/obj/item/device/flashlight/slime + gender = PLURAL + name = "glowing slime extract" + desc = "A glowing ball of what appears to be amber." + icon = 'icons/obj/lighting.dmi' + icon_state = "floor1" //not a slime extract sprite but... something close enough! + item_state = "slime" + w_class = 1 + m_amt = 0 + g_amt = 0 + brightness_on = 6 + on = 1 //Bio-luminesence has one setting, on. + +/obj/item/device/flashlight/slime/New() + SetLuminosity(brightness_on) + spawn(1) //Might be sloppy, but seems to be necessary to prevent further runtimes and make these work as intended... don't judge me! + update_brightness() + icon_state = initial(icon_state) + +/obj/item/device/flashlight/slime/attack_self(mob/user) + return //Bio-luminescence does not toggle. \ No newline at end of file diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index ec8075e8..371fe3b8 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -3,7 +3,7 @@ desc = "A device used to project your voice. Loudly." icon_state = "megaphone" item_state = "radio" - w_class = 1.0 + w_class = 2.0 flags = FPRINT | TABLEPASS | CONDUCT var/spamcheck = 0 diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index 85e6f3c2..0b23c97f 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -25,33 +25,200 @@ if (!in_range(src, user)) return user.set_machine(src) - var/dat = "Personal AI Device
" - if(pai && (!pai.master_dna || !pai.master)) - dat += "Imprint Master DNA
" + var/dat = {" + + + + + + + "} + if(pai) - dat += "Installed Personality: [pai.name]
" - dat += "Prime directive:
[pai.pai_law0]
" - dat += "Additional directives:
[pai.pai_laws]
" - dat += "Configure Directives
" + dat += {" + Personal AI Device

+ + + + + + + + + + + + + +
Installed Personality:[pai.name]
Prime directive:[pai.pai_law0]
Additional directives:[pai.pai_laws]
+
+ "} + dat += {" + + +
+ Configure Directives +
+ "} + if(pai && (!pai.master_dna || !pai.master)) + dat += {" + + +
+ Imprint Master DNA +
+ "} dat += "
" - dat += "

Device Settings


" if(radio) - dat += "Radio Uplink
" - dat += "Transmit: [(radio.wires & 4) ? "Enabled" : "Disabled"]
" - dat += "Receive: [(radio.wires & 2) ? "Enabled" : "Disabled"]
" - dat += "Signal Pulser: [(radio.wires & 1) ? "Enabled" : "Disabled"]
" + dat += "Radio Uplink" + dat += {" + + + + + + + + + + + + + +
Transmit:[(radio.wires & 4) ? "En" : "Dis" ]abled + +
Receive:[(radio.wires & 2) ? "En" : "Dis" ]abled + +
Signal Pulser:[(radio.wires & 1) ? "En" : "Dis" ]abled + +
+
+ "} else dat += "Radio Uplink
" dat += "Radio firmware not loaded. Please install a pAI personality to load firmware.
" - dat += "\[Wipe current pAI personality\]
" + dat += {" + + +
Wipe current pAI personality + +
+ "} else if(looking_for_personality) - dat += "Searching for a personality..." - dat += "\[View available personalities\]
" + dat += {" + pAI Request Module

+

Requesting AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.

+ Searching for personalities

+ + + + + +
+ Refresh available personalities +

+ "} else - dat += "No personality is installed.
" - dat += "\[Request personal AI personality\]
" - dat += "Each time this button is pressed, a request will be sent out to any available personalities. Check back often and alot time for personalities to respond. This process could take anywhere from 15 seconds to several minutes, depending on the available personalities' timeliness." + dat += {" + pAI Request Module

+

No personality is installed.

+ + + + +
Request personality +
+
+

Each time this button is pressed, a request will be sent out to any available personalities. Check back often give plenty of time for personalities to respond. This process could take anywhere from 15 seconds to several minutes, depending on the available personalities' timeliness.

+ "} user << browse(dat, "window=paicard") onclose(user, "paicard") return @@ -96,7 +263,7 @@ if(newlaws) pai.pai_laws = newlaws pai << "Your supplemental directives have been updated. Your new directives are:" - pai << "Prime Directive :
[pai.pai_law0]" + pai << "Prime Directive:
[pai.pai_law0]" pai << "Supplemental Directives:
[pai.pai_laws]" attack_self(usr) diff --git a/code/game/objects/items/devices/pipe_painter.dm b/code/game/objects/items/devices/pipe_painter.dm index e066a0b1..3a062adc 100644 --- a/code/game/objects/items/devices/pipe_painter.dm +++ b/code/game/objects/items/devices/pipe_painter.dm @@ -7,9 +7,15 @@ var/mode = "grey" /obj/item/device/pipe_painter/afterattack(atom/A, mob/user as mob) - if(!istype(A,/obj/machinery/atmospherics/pipe) || istype(A,/obj/machinery/atmospherics/pipe/tank) || istype(A,/obj/machinery/atmospherics/pipe/vent) || istype(A,/obj/machinery/atmospherics/pipe/simple/heat_exchanging) || istype(A,/obj/machinery/atmospherics/pipe/simple/insulated)) + if(!istype(A,/obj/machinery/atmospherics/pipe) || istype(A,/obj/machinery/atmospherics/pipe/tank) || istype(A,/obj/machinery/atmospherics/pipe/vent) || istype(A,/obj/machinery/atmospherics/pipe/simple/heat_exchanging) || istype(A,/obj/machinery/atmospherics/pipe/simple/insulated) || !in_range(user, A)) return var/obj/machinery/atmospherics/pipe/P = A + + var/turf/T = P.loc + if (P.level < 2 && T.level==1 && isturf(T) && T.intact) + user << "\red You must remove the plating first." + return + P.pipe_color = mode user.visible_message("[user] paints \the [P] [mode].","You paint \the [P] [mode].") P.update_icon() diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 4e8b9825..d00825cf 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -218,7 +218,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use del(A) return -/obj/item/device/radio/talk_into(mob/living/M as mob, message, channel) +/obj/item/device/radio/talk_into(mob/living/M as mob, message, channel, var/verb = "says", var/datum/language/speaking = null) if(!on) return // the device has to be on // Fix for permacell radios, but kinda eh about actually fixing them. if(!M || !message) return @@ -348,7 +348,9 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use "type" = 0, // determines what type of radio input it is: normal broadcast "server" = null, // the last server to log this signal "reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery - "level" = position.z // The source's z level + "level" = position.z, // The source's z level + "language" = speaking, + "verb" = verb ) signal.frequency = connection.frequency // Quick frequency set @@ -401,7 +403,9 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use "type" = 0, "server" = null, "reject" = 0, - "level" = position.z + "level" = position.z, + "language" = speaking, + "verb" = verb ) signal.frequency = connection.frequency // Quick frequency set @@ -423,7 +427,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use Broadcast_Message(connection, M, voicemask, pick(M.speak_emote), src, message, displayname, jobname, real_name, M.voice_name, - filter_type, signal.data["compression"], list(position.z), connection.frequency) + filter_type, signal.data["compression"], list(position.z), connection.frequency,verb,speaking) @@ -596,11 +600,13 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use else R.show_message(rendered, 2) -/obj/item/device/radio/hear_talk(mob/M as mob, msg) +/obj/item/device/radio/hear_talk(mob/M as mob, msg, var/verb = "says", var/datum/language/speaking = null) if (broadcasting) if(get_dist(src, M) <= canhear_range) - talk_into(M, msg) + talk_into(M, msg,null,verb,speaking) + + /* /obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index b321eb8a..449d6f7d 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -68,7 +68,7 @@ REAGENT SCANNER flags = FPRINT | TABLEPASS | CONDUCT slot_flags = SLOT_BELT throwforce = 3 - w_class = 1.0 + w_class = 2.0 throw_speed = 5 throw_range = 10 m_amt = 200 diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 2d80b654..4e9e90e8 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -19,10 +19,11 @@ throw_speed = 4 throw_range = 20 -/obj/item/device/taperecorder/hear_talk(mob/living/M as mob, msg) +/obj/item/device/taperecorder/hear_talk(mob/living/M as mob, msg, var/verb="says") if(recording) - var/ending = copytext(msg, length(msg)) + //var/ending = copytext(msg, length(msg)) timestamp+= timerecorded + /* if(M.stuttering) storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] [M.name] stammers, \"[msg]\"" return @@ -35,7 +36,8 @@ else if(ending == "!") storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] [M.name] exclaims, \"[msg]\"" return - storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] [M.name] says, \"[msg]\"" + */ + storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] [M.name] [verb], \"[msg]\"" return /obj/item/device/taperecorder/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -211,7 +213,7 @@ for(var/i=1,storedinfo.len >= i,i++) t1 += "[storedinfo[i]]
" P.info = t1 - P.name = "paper- 'Transcript'" + P.name = "Transcript" canprint = 0 sleep(300) canprint = 1 @@ -260,4 +262,4 @@ return else usr << "\red Stop what?" - return \ No newline at end of file + return diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm index 92908633..9870f88b 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplinks.dm @@ -30,7 +30,7 @@ A list of items and costs is stored under the datum of every game mode, alongsid for(var/D in ItemList) var/list/O = text2list(D, ":") if(O.len>0) - valid_items += O[1] + valid_items += O[1] diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 1992ea0b..f494ec89 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -47,12 +47,15 @@ /obj/item/borg/sight/thermal name = "\proper thermal vision" sight_mode = BORGTHERM + icon_state = "thermal" + icon = 'icons/obj/clothing/glasses.dmi' /obj/item/borg/sight/meson name = "\proper meson vision" sight_mode = BORGMESON - + icon_state = "meson" + icon = 'icons/obj/clothing/glasses.dmi' /obj/item/borg/sight/hud name = "hud" @@ -61,7 +64,8 @@ /obj/item/borg/sight/hud/med name = "medical hud" - + icon_state = "healthhud" + icon = 'icons/obj/clothing/glasses.dmi' New() ..() @@ -71,7 +75,8 @@ /obj/item/borg/sight/hud/sec name = "security hud" - + icon_state = "securityhud" + icon = 'icons/obj/clothing/glasses.dmi' New() ..() diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 0795146a..aee3cf58 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -4,7 +4,7 @@ icon = 'icons/obj/items.dmi' amount = 5 max_amount = 5 - w_class = 1 + w_class = 2 throw_speed = 4 throw_range = 20 var/heal_brute = 0 @@ -17,7 +17,7 @@ if ( ! (istype(user, /mob/living/carbon/human) || \ istype(user, /mob/living/silicon) || \ - istype(user, /mob/living/carbon/monkey) && ticker && ticker.mode.name == "monkey") ) + istype(user, /mob/living/carbon/monkey)) ) user << "\red You don't have the dexterity to do this!" return 1 diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 7ced60ab..8227b042 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -19,6 +19,13 @@ origin_tech = "materials=1" var/created_window = /obj/structure/window/basic +/obj/item/stack/sheet/glass/cyborg + name = "glass" + desc = "HOLY SHEET! That is a lot of glass." + singular_name = "glass sheet" + icon_state = "sheet-glass" + g_amt = 0 + created_window = /obj/structure/window/basic /obj/item/stack/sheet/glass/attack_self(mob/user as mob) construct_window(user) @@ -285,11 +292,14 @@ playsound(src.loc, 'sound/effects/glass_step.ogg', 50, 1) if(ishuman(M)) var/mob/living/carbon/human/H = M + + if(H.species.flags & IS_SYNTHETIC) + return + if( !H.shoes && ( !H.wear_suit || !(H.wear_suit.body_parts_covered & FEET) ) ) var/datum/organ/external/affecting = H.get_organ(pick("l_foot", "r_foot")) if(affecting.status & ORGAN_ROBOT) return - H.Weaken(3) if(affecting.take_damage(5, 0)) H.UpdateDamageIcon() diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 4e16db88..58dd82ab 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -125,6 +125,16 @@ var/global/list/datum/stack_recipe/plasma_recipes = list ( \ origin_tech = "materials=3" perunit = 2000 +/obj/item/stack/sheet/mineral/plastic/cyborg + name = "plastic sheets" + icon_state = "sheet-plastic" + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + perunit = 2000 + var/global/list/datum/stack_recipe/plastic_recipes = list ( \ new/datum/stack_recipe("plastic crate", /obj/structure/closet/crate/plastic, 10, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("plastic ashtray", /obj/item/ashtray/plastic, 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 3a157aa6..e50024d2 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -33,6 +33,8 @@ var/global/list/datum/stack_recipe/metal_recipes = list ( \ null, \ new/datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, time = 15, one_per_turf = 1, on_floor = 1), \ null, \ + new/datum/stack_recipe("cannon frame", /obj/item/weapon/cannonframe, 10, time = 15, one_per_turf = 0, on_floor = 0), \ + null, \ new/datum/stack_recipe("floor tile", /obj/item/stack/tile/plasteel, 1, 4, 20), \ new/datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60), \ null, \ @@ -129,9 +131,10 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \ new/datum/stack_recipe("table parts", /obj/item/weapon/table_parts/wood, 2), \ new/datum/stack_recipe("wooden chair", /obj/structure/stool/bed/chair/wood/normal, 3, time = 10, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("wooden barricade", /obj/structure/barricade/wooden, 5, time = 50, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("crossbow frame", /obj/item/weapon/crossbowframe, 5, time = 25, one_per_turf = 0, on_floor = 0), \ new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("coffin", /obj/structure/closet/coffin, 5, time = 15, one_per_turf = 1, on_floor = 1), \ - new/datum/stack_recipe("apiary", /obj/item/apiary, 10, time = 25, one_per_turf = 0, on_floor = 0), \ +// new/datum/stack_recipe("apiary", /obj/item/apiary, 10, time = 25, one_per_turf = 0, on_floor = 0) ) /obj/item/stack/sheet/wood @@ -141,6 +144,12 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \ icon_state = "sheet-wood" origin_tech = "materials=1;biotech=1" +/obj/item/stack/sheet/wood/cyborg + name = "wooden plank" + desc = "One can only guess that this is a bunch of wood." + singular_name = "wood plank" + icon_state = "sheet-wood" + /obj/item/stack/sheet/wood/New(var/loc, var/amount=null) recipes = wood_recipes return ..() diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 77aa58a1..32d704cd 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -148,7 +148,7 @@ src = null //dont kill proc after del() usr.before_take_item(oldsrc) del(oldsrc) - if (istype(O,/obj/item)) + if (istype(O,/obj/item) && istype(usr,/mob/living/carbon)) usr.put_in_hands(O) O.add_fingerprint(usr) //BubbleWrap - so newly formed boxes are empty diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 130457ce..dcfbf14f 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -585,4 +585,14 @@ force = 5 w_class = 4.0 slot_flags = SLOT_BACK -*/ \ No newline at end of file +*/ + +//This should really be somewhere else but I don't know where. w/e +/obj/item/weapon/inflatable_duck + name = "inflatable duck" + desc = "No bother to sink or swim when you can just float!" + icon_state = "inflatable" + item_state = "inflatable" + flags = FPRINT | TABLEPASS + icon = 'icons/obj/clothing/belts.dmi' + slot_flags = SLOT_BELT \ No newline at end of file diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm index 7d28c28d..69ec4708 100644 --- a/code/game/objects/items/trash.dm +++ b/code/game/objects/items/trash.dm @@ -4,7 +4,7 @@ //Added by Jack Rost /obj/item/trash icon = 'icons/obj/trash.dmi' - w_class = 1.0 + w_class = 2.0 desc = "This is rubbish." raisins name = "4no raisins" diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm index f4d106a9..7d738527 100644 --- a/code/game/objects/items/weapons/AI_modules.dm +++ b/code/game/objects/items/weapons/AI_modules.dm @@ -365,6 +365,20 @@ AI MODULES target.add_inherent_law("Minimize expenses.") target.show_laws() +/obj/item/weapon/aiModule/drone + name = "\improper 'Drone' core AI module" + desc = "A 'Drone' Core AI Module: 'Reconfigures the AI's core laws.'" + origin_tech = "programming=3;materials=4" + +/obj/item/weapon/aiModule/drone/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) + ..() + target.clear_inherent_laws() + target.add_inherent_law("Preserve, repair and improve the station to the best of your abilities.") + target.add_inherent_law("Cause no harm to the station or anything on it.") + target.add_inherent_law("Interfere with no being that is not a fellow drone.") + target.show_laws() + + /****************** P.A.L.A.D.I.N. **************/ /obj/item/weapon/aiModule/paladin // -- NEO diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 03ea6062..931edd3d 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -162,7 +162,7 @@ /obj/item/weapon/card/id/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() - if(istype(W,/obj/item/weapon/storage/wallet)) + if(istype(W,/obj/item/weapon/id_wallet)) user << "You slip [src] into [W]." src.name = "[src.registered_name]'s [W.name] ([src.assignment])" src.desc = W.desc @@ -200,7 +200,7 @@ access = list(access_maint_tunnels, access_syndicate, access_external_airlocks) origin_tech = "syndicate=3" var/registered_user=null - + /obj/item/weapon/card/id/syndicate/New(mob/user as mob) ..() if(!isnull(user)) // Runtime prevention on laggy starts or where users log out because of lag at round start. @@ -208,7 +208,7 @@ else registered_name = "Agent Card" assignment = "Agent" - name = "[registered_name]'s ID Card ([assignment])" + name = "[registered_name]'s ID Card ([assignment])" /obj/item/weapon/card/id/syndicate/afterattack(var/obj/item/weapon/O as obj, mob/user as mob, proximity) if(!proximity) return @@ -239,7 +239,7 @@ registered_user = user else if(!registered_user || registered_user == user) - if(!registered_user) registered_user = user // + if(!registered_user) registered_user = user // switch(alert("Would you like to display the ID, or retitle it?","Choose.","Rename","Show")) if("Rename") diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index d89e7734..091314c6 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -62,7 +62,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM throw_speed = 0.5 item_state = "cigoff" w_class = 1 - body_parts_covered = null + body_parts_covered = 0 attack_verb = list("burnt", "singed") var/lit = 0 var/icon_on = "cigon" //Note - these are in masks.dmi not in cigarette.dmi @@ -167,7 +167,12 @@ CIGARETTE PACKETS ARE IN FANCY.DM location.hotspot_expose(700, 5) if(reagents && reagents.total_volume) // check if it has any reagents at all if(iscarbon(loc) && (src == loc:wear_mask)) // if it's in the human/monkey mouth, transfer reagents to the mob + if(istype(loc, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = loc + if(H.species.flags & IS_SYNTHETIC) + return var/mob/living/carbon/C = loc + if(prob(15)) // so it's not an instarape in case of acid reagents.reaction(C, INGEST) reagents.trans_to(C, REAGENTS_METABOLISM) diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm index 4f94ecca..c981087b 100644 --- a/code/game/objects/items/weapons/implants/implanter.dm +++ b/code/game/objects/items/weapons/implants/implanter.dm @@ -51,7 +51,7 @@ src.imp = null update() - + return @@ -120,6 +120,12 @@ if (c.scanned) user << "\red Something is already scanned inside the implant!" return - imp:scanned = A + c.scanned = A + if(istype(A.loc,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = A.loc + H.u_equip(A) + else if(istype(A.loc,/obj/item/weapon/storage)) + var/obj/item/weapon/storage/S = A.loc + S.remove_from_storage(A) A.loc.contents.Remove(A) update() diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm index 0c05bcef..17ab2fee 100644 --- a/code/game/objects/items/weapons/manuals.dm +++ b/code/game/objects/items/weapons/manuals.dm @@ -19,7 +19,7 @@ - + @@ -38,16 +38,18 @@ -

Experienced user's guide

+

Experienced User's Guide

-

Setting up

+

Setting up the accelerator

  1. Wrench all pieces to the floor
  2. @@ -55,7 +57,7 @@
  3. Close all the panels with your screwdriver
-

Use

+

Using the accelerator

  1. Open the control panel
  2. @@ -66,7 +68,8 @@
- "} + + "} /obj/item/weapon/book/manual/supermatter_engine @@ -75,87 +78,109 @@ author = "Waleed Asad" title = "Supermatter Engine User's Guide" - dat = {"Engineering notes on single-stage Supermatter engine,
- -Waleed Asad
+ dat = {" + + + + +
+ Engineering notes on the single-stage supermatter engine,
+ -Waleed Asad

- Station,
- Exodus
+ Station,
+ Exodus

- A word of caution, do not enter the engine room, for any reason, without radiation protection and mesons on. The status of the engine may be unpredictable even when you believe it is .off.. This is an important level of personal protection.

+ A word of caution, do not enter the engine room for any reason without radiation protection and meson scanners on. The status of the engine may be unpredictable even when you believe it is 'off.' This is an important level of personal protection.

- The engine has two basic modes of functionality. He has observed that it is capable of both a safe level of operation and a modified, high output mode.

+ The engine has two basic modes of functionality. It has been observed that it is capable of both a safe level of operation and a modified, high output mode.

-
Notes on starting the basic function mode, dubbed .Heat-Primary Mode..


+

Heat-Primary Mode

+ Notes on starting the basic function mode +
    +
  1. Prepare collector arrays: As is standard, begin by wrenching them down, filling six plasma tanks with a plasma canister, and inserting the tank into the collectors one by one. Finally, initialize each collector.
  2. - 1. Prepare collector arrays. This is done standard to any text on their function by wrenching them down, filling six plasma tanks with a plasma canister, and inserting the tank into the collectors one by one. Finally, initialize each collector.

    +
  3. Prepare gas system: Before introducing any gas into the supermatter engine room, it is important to remember the small, but vital steps to preparing this section. First, set the input gas pump and output gas flow pump to 4500 kPa, or maximum flow. Second, switch the digital switching valve into the 'up' position, so the green light is on north side of the valve, in order to circulate the gas back toward the coolers and collectors.
  4. - 2. Prepare gas system. Before introducing any gas to the Supermatter engine room, it is important to remember the small but vital steps to preparing this section. First, set the input gas pump and output gas flow pump to 4500, or maximum flow. Second, switch the digital switching valve into the .up. position, in order to circulate the gas back toward the coolers and collectors.

    +
  5. Apply N2 gas: Retrieve the two N2 canisters from storage and bring them to the engine room. Attach one of them to the input section of the engine gas system located next to the collectors. Keep it attached until the N2 pressure is low enough to turn the canister light red. Replace it with the second canister to keep N2 pressure at optimal levels.
  6. - 3. Apply N2 gas. Retrieve the two N2 canisters from storage and bring them to the engine room. Attach one of them to the input section of the engine gas system located next to the collectors. Keep it attached until the N2 pressure is low enough to turn the canister light red. Replace it with the second canister to keep N2 pressure at optimal levels.

    +
  7. Open supermatter shielding: This button is located in the engine room, to the left of the engine monitoring room blast doors. At this point, the supermatter chamber is mostly a gas mixture of N2 and is producing no radiation. It is considered 'safe' up until this point. Do not forget radiation shielding and meson scanners.
  8. - 4. Open Supermatter shielding. This button is located on the far right of the engine room. At this point, the Supermatter chamber is mostly a gas mix of N2 and is producing no radiation. It is considered .safe. up until this point. Do not forget radiation shielding and mesons.

    +
  9. Begin primary emitter burst series: Begin by firing four shots into the supermatter using the emitter. It is important to move to this step quickly. The onboard SMES units may not have enough power to run the emitters if left alone too long on-station. This engine can produce enough power on its own to run the entire station, ignoring the SMES units completely, and is wired to do so.
  10. - 5. Begin primary emitter burst series. This means firing a single emitter for its first four shots. It is important to move to this step quickly. The onboard SMES units may not have enough power to run the emitters if left alone too long on-station. This engine can produce enough power on its own to run the entire station, ignoring the SMES units completely, and is wired to do so.

    +
  11. Switch SMES units to primary settings: Maximize input and set the devices to automatically charge, additionally turn their outputs on if they are off unless power is to be saved (Which can be useful in case of later failures).
  12. - 6. Switch SMES units to primary settings. Maximize input and set the devices to automatically charge, additionally turn their outputs on if they are off unless power is to be saved (Which can be useful in case of later failures.)

    +
  13. Begin secondary emitter burst series: Before firing the emitter again, check the power in the line with a multimeter (Do not forget electrical gloves). The engine is running at high efficiency when the value exceeds 200,000 power units.
  14. - 7. Begin secondary emitter burst series. Before firing the emitter again, check the power in the line with a multimeter (Do not forget electrical gloves.) The engine is running at high efficiency when the value exceeds 200,000 power units.

    - - 8. Maintain engine power. When power in the lines gets low, add an additional emitter burst series to bring power to normal levels.


    +
  15. Maintain engine power: When power in the lines get low, add an additional emitter burst series to bring power to normal levels.
  16. +
+

O2-Reaction Mode

-
The second mode for running the engine uses a gas mix to produce a reaction within the Supermatter. This mode requires CE or Atmospheric help to setup. This has been dubbed the .O2-Reaction Mode..


+ The second mode for running the engine uses a gas mixture to produce a reaction within the supermatter. This mode requires the CE's or Atmospheric's help to set up. This is called 'O2-Reaction Mode.'

- THIS MODE CAN CAUSE A RUNAWAY REACTION, LEADING TO CATASTROPHIC FAILURE IF NOT MAINTAINED. NEVER FORGET ABOUT THE ENGINE IN THIS MODE.

+ THIS MODE CAN CAUSE A RUNAWAY REACTION, LEADING TO CATASTROPHIC FAILURE IF NOT MAINTAINED. NEVER FORGET ABOUT THE ENGINE IN THIS MODE.

- Additionally, this mode can be used for what is called a .Cold Start.. If the station has no power in the SMES to run the emitters, using this mode will allow enough power output to run them, and quickly reach an acceptable level of power output.

+ Additionally, this mode can be used for what is called a 'Cold Start.' If the station has no power in the SMES to run the emitters, using this mode will allow enough power output to run them, and quickly reach an acceptable level of power output.

- 1. Prepare collector arrays. This is done standard to any text on their function by wrenching them down, filling six plasma tanks with a plasma canister, and inserting the tank into the collectors one by one. Finally, initialize each collector.

+
    +
  1. Prepare collector arrays: As is standard, begin by wrenching them down, filling six plasma tanks with a plasma canister, and inserting the tank into the collectors one by one. Finally, initialize each collector.
  2. - 2. Prepare gas system. Before introducing any gas to the Supermatter engine room, it is important to remember the small but vital steps to preparing this section. First, set the input gas pump and output gas flow pump to 4500, or maximum flow. Second, switch the digital switching valve into the .up. position, in order to circulate the gas back toward the coolers and collectors.

    +
  3. Prepare gas system: Before introducing any gas into the supermatter engine room, it is important to remember the small, but vital steps to preparing this section. First, set the input gas pump and output gas flow pump to 4500 kPa, or maximum flow. Second, switch the digital switching valve into the 'up' position, so the green light is on north side of the valve, in order to circulate the gas back toward the coolers and collectors.
  4. - 3. Modify the engine room filters. Unlike the Heat-Primary Mode, it is important to change the filters attached to the gas system to stop filtering O2, and start filtering Carbon Molecules. O2-Reaction Mode produces far more plasma than Heat-Primary, therefor filtering it off is essential.

    +
  5. Modify the engine room filters: Unlike the Heat-Primary Mode, it is important to change the filters attached to the gas system to stop filtering O2, and start filtering carbon molecules. O2-Reaction Mode produces far more plasma than Heat-Primary, therefore filtering it off is essential.
  6. - 4. Switch SMES units to primary settings. Maximize input and set the devices to automatically charge, additionally turn their outputs on if they are off unless power is to be saved (Which can be useful in case of later failures.) If you check the power in the system lines at this point you will find that it is constantly going up. Indeed, with just the addition of O2 to the Supermatter, it will begin outputting power.

    +
  7. Switch SMES units to primary settings: Maximize input and set the devices to automatically charge, additionally turn their outputs on if they are off unless power is to be saved (Which can be useful in case of later failures). If you check the power in the system lines at this point, you will find that it is constantly going up. Indeed, with just the addition of O2 to the supermatter, it will begin outputting power.
  8. - 5. Begin primary emitter burst series. Fire a single emitter for a series of four pulses, or a single series, and turn it off. Do not over power the Supermatter. The reaction is self sustaining and propagating. As long as O2 is in the chamber, it will continue outputting MORE power.

    +
  9. Begin primary emitter burst series: Begin by firing four shots into the supermatter using the emitter. Do not over power the supermatter. The reaction is self sustaining and propagating. As long as O2 is in the chamber, it will continue outputting MORE power.
  10. - 6. Maintain follow up operations. Remember to check the temp of the core gas and switch to the Heat-Primary function, or vent the core room when problems begin if required.

    +
  11. Maintain follow up operations: Remember to check the temperature of the core gas and switch to the Heat-Primary function, or vent the core room when problems begin if required.
  12. +

- Notes on Supermatter Reaction Function and Drawbacks-

+

Notes on Supermatter Reaction Function and Drawbacks

- After several hours of observation an interesting phenomenon was witnessed. The Supermatter undergoes a constant self-sustaining reaction when given an extremely high O2 concentration. Anything about 80% or higher typically will cause this reaction. The Supermatter will continue to react whenever this gas mix is in the same room as the Supermatter.

+ After several hours of observation, an interesting phenomenon was witnessed. The supermatter undergoes a constant, self-sustaining reaction when given an extremely high O2 concentration. Anything about 80% or higher typically will cause this reaction. The supermatter will continue to react whenever this gas mixture is in the same room as the supermatter.

- To understand why O2-Reaction mode is dangerous, the core principle of the Supermatter must be understood. The Supermatter emits three things when .not safe,. that is any time it is giving off power. These things are:

+ To understand why O2-Reaction mode is dangerous, the core principle of the supermatter must be understood. The supermatter emits three things when 'not safe,' that is any time it is giving off power. These things are:
- *Radiation (which is converted into power by the collectors,)
- *Heat (which is removed via the gas exchange system and coolers,)
- *External gas (in the form of plasma and O2.)
+
    +
  • Radiation (which is converted into power by the collectors)

  • +
  • Heat (which is removed via the gas exchange system and coolers)

  • +
  • External gas (in the form of plasma and O2)

  • +

- When in Heat-Primary mode, far more heat and plasma are produced than radiation. In O2-Reaction mode, very little heat and only moderate amounts of plasma are produced, however HUGE amounts of energy leaving the Supermatter is in the form of radiation.

+ When in Heat-Primary mode, far more heat and plasma are produced than radiation. In O2-Reaction mode, very little heat and only moderate amounts of plasma are produced, however HUGE amounts of energy leaving the supermatter is in the form of radiation.

- The O2-Reaction engine mode has a single drawback which has been eluded to more than once so far and that is very simple. The engine room will continue to grow hotter as the constant reaction continues. Eventually, there will be what he calls the .critical gas mix.. This is the point at which the constant adding of plasma to the mix of air around the Supermatter changes the gas concentration to below the tolerance. When this happens, two things occur. First, the Supermatter switches to its primary mode of operation where in huge amounts of heat are produced by the engine rather than low amounts with high power output. Second, an uncontrollable increase in heat within the Supermatter chamber will occur. This will lead to a spark-up, igniting the plasma in the Supermatter chamber, wildly increasing both pressure and temperature.

+ The O2-Reaction engine mode has a single drawback which has been eluded to more than once so far and that is very simple. The engine room will continue to grow hotter as the constant reaction continues. Eventually, there will be what is called a 'critical gas mixture.' This is the point at which the constant adding of plasma to the mixture of air around the supermatter changes the gas concentration to below the tolerance. When this happens, two things occur. First, the supermatter switches to its primary mode of operation wherein huge amounts of heat are produced by the engine rather than low amounts with high power output. Second, an uncontrollable increase in heat within the supermatter chamber will occur. This will lead to a spark-up, igniting the plasma in the supermatter chamber, wildly increasing both pressure and temperature.

- While the O2-Reaction mode is dangerous, it does produce heavy amounts of energy. Consider using this mode only in short amounts to fill the SMES, and switch back later in the shift to keep things flowing normally.

+ While the O2-Reaction mode is dangerous, it does produce heavy amounts of energy. Consider using this mode only in short amounts to fill the SMES, and switch back later in the shift to keep things flowing normally.

- Notes on Supermatter Containment and Emergency Procedures-

+

Notes on Supermatter Containment and Emergency Procedures

- While a constant vigil on the Supermatter is not required, regular checkups are important. Verify the temp of gas leaving the Supermatter chamber for unsafe levels, and ensure that the plasma in the chamber is at a safe concentration. Of course, also make sure the chamber is not on fire. A fire in the core chamber is very difficult to put out. As any Toxin scientist can tell you, even low amounts of plasma can burn at very high temperatures. This burning creates a huge increase in pressure and more importantly, temperature of the crystal itself.

+ While a constant vigil on the supermatter is not required, regular checkups are important. Check the temperature of gas leaving the supermatter chamber for unsafe levels and ensure that the plasma in the chamber is at a safe concentration. Of course, also make sure the chamber is not on fire. A fire in the core chamber is very difficult to put out. As any toxin scientist can tell you, even low amounts of plasma can burn at very high temperatures. This burning creates a huge increase in pressure and more importantly, temperature of the crystal itself.

- The Supermatter is strong, but not invincible. When the Supermatter is heated too much, its crystal structure will attempt to liquify. The change in atomic structure of the Supermatter leads to a single reaction, a massive explosion. The computer chip attached to the Supermatter core will warn the station when stability is threatened. It will then offer a second warning, when things have become dangerously close to total destruction of the core.

+ The supermatter is strong, but not invincible. When the supermatter is heated too much, its crystal structure will attempt to liquefy. The change in atomic structure of the supermatter leads to a single reaction, a massive explosion. The computer chip attached to the supermatter core will warn the station when stability is threatened. It will then offer a second warning, when things have become dangerously close to total destruction of the core.

- Located both within the CE office and engine room is the vent control button. This button allows the Core Vent Controls to be accessed, venting the room to space. Remember however, that this process takes time. If a fire is raging, and the pressure is higher than fathomable, it will take a great deal of time to vent the room. Also located in the CE.s office is the emergency core eject button. A new core can be ordered from cargo. It is often not worth the lives of the crew to hold on to it, not to mention the structural damage. However, if by some mistake the Supermatter is pushed off or removed from the mass ejector it sits on, manual reposition will be required. Which is very dangerous and often leads to death.

+ Located both within the CE office and engine room is the engine ventilatory control button. This button allows the core vent controls to be accessed, venting the room to space. Remember however, that this process takes time. If a fire is raging, and the pressure is higher than fathomable, it will take a great deal of time to vent the room. Also located in the CE's office is the emergency core eject button. A new core can be ordered from cargo. It is often not worth the lives of the crew to hold on to it, not to mention the structural damage. However, if by some mistake the supermatter is pushed off or removed from the mass driver it sits on, manual reposition will be required. Which is very dangerous and often leads to death.

- The Supermatter is extremely dangerous. More dangerous than people give it credit for. It can destroy you in an instant, without hesitation, reducing you to a pile of dust. When working closely with Supermatter it is.. suggested to get a genetic backup and do not wear any items of value to you. The Supermatter core can be pulled if grabbed properly by the base, but pushing is not possible.


+ The supermatter is extremely dangerous. More dangerous than people give it credit for. It can destroy you in an instant, without hesitation, reducing you to a pile of dust. When working closely with supermatter, it is suggested to get a genetic backup and do not wear any items of value to you. The supermatter core can be pulled if grabbed properly by the base, but pushing is not possible.

- In Closing-

+

In Closing

- Remember that the Supermatter is dangerous, and the core is dangerous still. Venting the core room is always an option if you are even remotely worried, utilizing Atmospherics to properly ready the room once more for core function. It is always a good idea to check up regularly on the temperature of gas leaving the chamber, as well as the power in the system lines. Lastly, once again remember, never touch the Supermatter with anything. Ever.

+ Remember that the supermatter is dangerous, and the core is dangerous still. Venting the core room is always an option if you are even remotely worried, utilizing Atmospherics to properly ready the room once more for core function. It is always a good idea to check up regularly on the temperature of gas leaving the chamber, as well as the power in the system lines. Lastly, once again remember, never touch the supermatter with anything. Ever.

- -Waleed Asad, Senior Engine Technician."} + -Waleed Asad, Senior Engine Technician + + "} /obj/item/weapon/book/manual/engineering_hacking name = "Hacking" @@ -189,48 +214,51 @@ h1 {font-size: 18px; margin: 15px 0px 5px;} h2 {font-size: 15px; margin: 15px 0px 5px;} li {margin: 2px 0px 2px 15px;} - ul {list-style: none; margin: 5px; padding: 0px;} + ul {margin: 5px; padding: 0px;} ol {margin: 5px; padding: 0px 15px;} + body {font-size: 13px; font-family: Verdana;} -

Singularity Safety in Special Circumstances

+

Singularity Safety in Special Circumstances

-

Power outage

+

Power outage

- A power problem has made the entire station loose 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: Get to the Area Power Controller which controls the power to the emitters.
- Step four: 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!!!
-

+ 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: -

Shields get damaged

+
    +
  1. PANIC!
  2. +
  3. Get your ass over to engineering! QUICKLY!!!
  4. +
  5. Get to the Area Power Controller which controls the power to the emitters.
  6. +
  7. Swipe it with your ID card - if it doesn't unlock, continue with step 15.
  8. +
  9. Open the console and disengage the cover lock.
  10. +
  11. Pry open the APC with a Crowbar.
  12. +
  13. Take out the empty power cell.
  14. +
  15. Put in the new, full power cell - if you don't have one, continue with step 15.
  16. +
  17. Quickly put on a Radiation suit.
  18. +
  19. Check if the singularity field generators withstood the down-time - if they didn't, continue with step 15.
  20. +
  21. 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.
  22. +
  23. Grab your crowbar and pry away the tile closest to the APC.
  24. +
  25. Use the wirecutters to cut the wire which is connecting the grid to the terminal.
  26. +
  27. Go to the bar and tell the guys how you saved them all. Stop reading this guide here.
  28. +
  29. GET THE FUCK OUT OF THERE!!!
  30. +
- Step one: GET THE FUCK OUT OF THERE!!! FORGET THE WOMEN AND CHILDREN, SAVE YOURSELF!!!
+

Shields get damaged

+ +
    +
  1. GET THE FUCK OUT OF THERE!!! FORGET THE WOMEN AND CHILDREN, SAVE YOURSELF!!!
  2. +
- - "} + + "} /obj/item/weapon/book/manual/hydroponics_pod_people - name = "The Diona Harvest - From seed to market" + name = "The Diona Harvest - From Seed to Market" icon_state ="bookHydroponicsPodPeople" author = "Farmer John" - title = "The Diona Harvest - From seed to market" + title = "The Diona Harvest - From Seed to Market" dat = {" @@ -238,20 +266,25 @@ h1 {font-size: 18px; margin: 15px 0px 5px;} h2 {font-size: 15px; margin: 15px 0px 5px;} li {margin: 2px 0px 2px 15px;} - ul {list-style: none; margin: 5px; padding: 0px;} + ul {margin: 5px; padding: 0px;} ol {margin: 5px; padding: 0px 15px;} + body {font-size: 13px; font-family: Verdana;} -

Growing Diona

+

Growing a Diona

- Growing Diona is easy! + Growing a Diona is easy!

    -
  1. Plant the seeds.
  2. -
  3. Tend to the plants water and nutrition levels until it is time to harvest the Diona.
  4. +
  5. Take a syringe of blood from the body you wish to turn into a Diona.
  6. +
  7. Inject 5 units of blood into the pack of dionaea-replicant seeds.
  8. +
  9. Plant the seeds.
  10. +
  11. Tend to the plants water and nutrition levels until it is time to harvest the Diona.

+ Note that for a successful harvest, the body from which the blood was taken from must be dead BEFORE harvesting the pod, however the pod can be growing while they are still alive. Otherwise, the soul would not be able to migrate to the new Diona body.

+ It really is that easy! Good luck! @@ -260,27 +293,29 @@ /obj/item/weapon/book/manual/medical_cloning - name = "Cloning techniques of the 26th century" + name = "Cloning Techniques of the 26th Century" icon_state ="bookCloning" author = "Medical Journal, volume 3" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "Cloning techniques of the 26th century" + title = "Cloning Techniques of the 26th Century" dat = {" -

How to Clone People

- So there’s 50 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. +

How to Clone People

+ So there are 50 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
  2. @@ -288,7 +323,7 @@
  3. Put body in cloning machine
  4. Scan body
  5. Clone body
  6. -
  7. Get clean Structurel Enzymes for the body
  8. +
  9. Get clean Structural Enzymes for the body
  10. Put body in morgue
  11. Await cloned body
  12. Cryo and use the clean SE injector
  13. @@ -296,54 +331,54 @@
  14. Send person on their way
-

Step 1: Acquire body

+

Step 1: Acquire body

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, great! Move on to the next step. -

Step 2: Strip body

- The cloning machine does not like abiotic items. What this means is you can’t clone anyone if they’re wearing clothes, so take all of it off. If it’s just one person, it’s courteous to put their possessions in the closet. - If you have about seven people awaiting cloning, just leave the piles where they are, but don’t mix them around and for God’s sake don’t let people in to steal them. +

Step 2: Strip body

+ The cloning machine does not like abiotic items. What this means is you can't clone anyone if they're wearing clothes or holding things, so take all of it off. If it's just one person, it's courteous to put their possessions in the closet. + If you have about seven people awaiting cloning, just leave the piles where they are, but don't mix them around and for God's sake don't let people in to steal them. -

Step 3: Put body in cloning machine

+

Step 3: Put body in cloning machine

Grab the body and then put it inside the DNA modifier. If you cannot do this, then you messed up at Step 2. Go back and check you took EVERYTHING off - a commonly missed item is their headset. -

Step 4: Scan body

- 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)! - 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: Scan body

+ Go onto the computer and scan the body by pressing 'Scan - <Subject Name Here>.' 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)! + 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 5: Clone body

- 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: Clone body

+ 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 6: Get clean SEs for body

+

Step 6: Get clean SEs for body

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 to prepare 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. + For this reason, you need to prepare 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. + 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. -

Step 7: Put body in morgue

+

Step 7: Put body in morgue

Now that the cloning process has been initiated and you have some 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. - 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 one of the nearby pens to label the bed “CHEF MEAT” in order to avoid confusion. + 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 one of the nearby pens to label the bed "CHEF MEAT" in order to avoid confusion. -

Step 8: Await cloned body

- Now go back to the lab and wait for your patient to be cloned. It won’t be long now, I promise. +

Step 8: Await cloned body

+ Now go back to the lab and wait for your patient to be cloned. It won't be long now, I promise. -

Step 9: Cyo and clean clean SE injector on person

- Has your body been cloned yet? Great! As soon as the guy pops out, grab them and stick them in cryo. Clonexadone and Cryoxadone help rebuild their genetic material. Then grab your cleanr SE injector and jab it in them. Once you’ve injected them, +

Step 9: Cryo and clean SE injector on person

+ Has your body been cloned yet? Great! As soon as the guy pops out, grab them and stick them in cryo. Clonexadone and Cryoxadone help rebuild their genetic material. Then grab your clean SE injector and jab it in them. Once you've injected them, they now have clean Structural Enzymes and their defects, if any, will disappear in a short while. -

Step 10: Give person 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: Give person 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 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. +

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. +

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. @@ -362,17 +397,20 @@ h1 {font-size: 18px; margin: 15px 0px 5px;} h2 {font-size: 15px; margin: 15px 0px 5px;} li {margin: 2px 0px 2px 15px;} - ul {list-style: none; margin: 5px; padding: 0px;} + ul {margin: 5px; padding: 0px;} + ul.a {list-style-type: none; margin: 5px; padding: 0px;} ol {margin: 5px; padding: 0px 15px;} + body {font-size: 13px; font-family: Verdana;}

+
Weyland-Yutani - Building Better Worlds

Autonomous Power Loader Unit \"Ripley\"

Specifications:

-
    +

    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"
    A Service Cyborg comes with: + 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."
    A Service Cyborg comes with:
    • Shaker
    • -
    • Industrail Dropper
    • +
    • Industrial Dropper
    • Platter
    • Beer Synthesizer
    • Zippo Lighter
    • @@ -600,7 +643,7 @@
      • Metal
      • Two Flashes
      • -
      • One Power Cell (Preferrably rated to 15000w)
      • +
      • One Power Cell (Preferably rated to 15000w)
      • Some electrical wires
      • One Human Brain
      • One Man-Machine Interface
      • @@ -612,7 +655,7 @@
      • Once you have a Robot Head, place your two flashes inside the eye sockets
      • Once you have your Robot Chest, wire the Robot chest, then insert the power cell
      • Attach all of the Robot parts to the Robot frame
      • -
      • Insert the Man-Machine Interface (With the Brain inside) Into the Robot Body
      • +
      • Insert the Man-Machine Interface (With the Brain inside) into the Robot Body
      • Congratulations! You have a new cyborg!
      • @@ -620,7 +663,7 @@ 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: + 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 as follows:
        1. Unlock the Cyborg's Interface by swiping your ID on it
        2. Open the Cyborg's outer panel using a crowbar
        3. @@ -633,71 +676,71 @@

          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. -
          +
        4. Follow Steps 1 - 3 of "Replacing a Cyborg's Power Cell"
        5. +
        6. Open the cyborg's internal wiring panel by using a screwdriver to unsecure the panel
        7. +
        + 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). +

        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. +

        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. +

        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 of 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. +

        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. -
        +

        "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 immobilize 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 LawSync
        14. +
        15. Proceed to a cyborg upload console. NanoTrasen usually places these in the same location as AI upload 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. +

        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/weapon/book/manual/security_space_law name = "Space Law" - desc = "A set of Nanotrasen guidelines for keeping law and order on their space stations." + desc = "A set of NanoTrasen guidelines for keeping law and order on their space stations." icon_state = "bookSpaceLaw" - author = "Nanotrasen" + author = "NanoTrasen" title = "Space Law" dat = {" @@ -706,7 +749,8 @@ - + + @@ -718,43 +762,44 @@ name = "NT Medical Diagnostics Manual" desc = "First, do no harm. A detailed medical practitioner's guide." icon_state = "bookMedical" - author = "Nanotrasen Medicine Department" + author = "NanoTrasen Medicine Department" title = "NT Medical Diagnostics Manual" - dat = {" + dat = {" + + + + +
        +

        The Oath

        - - + The Medical Oath sworn by recognised medical practitioners in the employ of NanoTrasen
        - - The Oath
        - The Medical Oath sworn by recognised medical practitioners in the employ of Nanotrasen
        -
        - Now, as a new doctor, I solemnly promise that I will to the best of my ability serve humanity-caring for the sick, promoting good health, and alleviating pain and suffering.
        -
        - I recognise that the practice of medicine is a privilege with which comes considerable responsibility and I will not abuse my position.
        -
        - I will practise medicine with integrity, humility, honesty, and compassion-working with my fellow doctors and other colleagues to meet the needs of my patients.
        -
        - I shall never intentionally do or administer anything to the overall harm of my patients.
        -
        - I will not permit considerations of gender, race, religion, political affiliation, sexual orientation, nationality, or social standing to influence my duty of care.
        -
        - I will oppose policies in breach of human rights and will not participate in them. I will strive to change laws that are contrary to my profession's ethics and will work towards a fairer distribution of health resources.
        -
        - I will assist my patients to make informed decisions that coincide with their own values and beliefs and will uphold patient confidentiality.
        -
        - I will recognise the limits of my knowledge and seek to maintain and increase my understanding and skills throughout my professional life. I will acknowledge and try to remedy my own mistakes and honestly assess and respond to those of others.
        -
        - I will seek to promote the advancement of medical knowledge through teaching and research.
        -
        - I make this declaration solemnly, freely, and upon my honour.
        +
          +
        1. Now, as a new doctor, I solemnly promise that I will, to the best of my ability, serve humanity-caring for the sick, promoting good health, and alleviating pain and suffering.
        2. +
        3. I recognise that the practice of medicine is a privilege with which comes considerable responsibility and I will not abuse my position.
        4. +
        5. I will practise medicine with integrity, humility, honesty, and compassion-working with my fellow doctors and other colleagues to meet the needs of my patients.
        6. +
        7. I shall never intentionally do or administer anything to the overall harm of my patients.
        8. +
        9. I will not permit considerations of gender, race, religion, political affiliation, sexual orientation, nationality, or social standing to influence my duty of care.
        10. +
        11. I will oppose policies in breach of human rights and will not participate in them. I will strive to change laws that are contrary to my profession's ethics and will work towards a fairer distribution of health resources.
        12. +
        13. I will assist my patients to make informed decisions that coincide with their own values and beliefs and will uphold patient confidentiality.
        14. +
        15. I will recognise the limits of my knowledge and seek to maintain and increase my understanding and skills throughout my professional life. I will acknowledge and try to remedy my own mistakes and honestly assess and respond to those of others.
        16. +
        17. I will seek to promote the advancement of medical knowledge through teaching and research.
        18. +
        19. I make this declaration solemnly, freely, and upon my honour.
        20. +

        -
        +
        - - - + + + "} @@ -789,9 +834,11 @@ @@ -799,39 +846,39 @@

        Food for Dummies

        Here is a guide on basic food recipes and also how to not poison your customers accidentally. -

        Basics:

        +

        Basics:

        Knead an egg and some flour to make dough. Bake that to make a bun or flatten and cut it. -

        Burger:

        +

        Burger:

        Put a bun and some meat into the microwave and turn it on. Then wait. -

        Bread:

        +

        Bread:

        Put some dough and an egg into the microwave and then wait. -

        Waffles:

        - Add two lumps of dough and 10u of sugar to the microwave and then wait. +

        Waffles:

        + Add two lumps of dough and 10 units of sugar to the microwave and then wait. -

        Popcorn:

        +

        Popcorn:

        Add 1 corn to the microwave and wait. -

        Meat Steak:

        - Put a slice of meat, 1 unit of salt and 1 unit of pepper into the microwave and wait. +

        Meat Steak:

        + Put a slice of meat, 1 unit of salt, and 1 unit of pepper into the microwave and wait. -

        Meat Pie:

        +

        Meat Pie:

        Put a flattened piece of dough and some meat into the microwave and wait. -

        Boiled Spaghetti:

        +

        Boiled Spaghetti:

        Put the spaghetti (processed flour) and 5 units of water into the microwave and wait. -

        Donuts:

        +

        Donuts:

        Add some dough and 5 units of sugar to the microwave and wait. -

        Fries:

        +

        Fries:

        Add one potato to the processor, then bake them in the microwave. - + "} @@ -846,89 +893,91 @@ -

        Drinks for dummies

        - Heres a guide for some basic drinks. +

        Drinks for Dummies

        + Here's a guide for some basic drinks. -

        Manly Dorf:

        - Mix ale and beer into a glass. +

        Black Russian:

        + Mix vodka and Kahlua 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:

        +

        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:

        +

        Classic Martini:

        Mix vermouth and gin into a glass. +

        Gin Tonic:

        + Mix gin and tonic into a glass. + +

        Grog:

        + Mix rum and water into a glass. + +

        Irish Cream:

        + Mix cream and whiskey into a glass. + +

        The Manly Dorf:

        + Mix ale and beer into a glass. + +

        Mead:

        + Mix enzyme, water, and sugar into a glass. + +

        Screwdriver:

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

        Detective Work

        + + + + +

        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! + 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 perpetrator, 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 perpetrator, 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 ship's finest vodka, you did it!
        24. +
        +

        + It really is that easy! Good luck! - + "} /obj/item/weapon/book/manual/nuclear @@ -938,34 +987,49 @@ title = "Fission Mailed: Nuclear Sabotage 101" dat = {" - Nuclear Explosives 101:
        - Hello and thank you for choosing the Syndicate for your nuclear information needs.
        - Today's crash course will deal with the operation of a Fusion Class Nanotrasen made Nuclear Device.
        - First and foremost, DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE.
        - Pressing any button on the compacted bomb will cause it to extend and bolt itself into place.
        - If this is done to unbolt it one must completely log in which at this time may not be possible.
        - To make the nuclear device functional:
        -

      • Place the nuclear device in the designated detonation zone.
      • -
      • Extend and anchor the nuclear device from its interface.
      • -
      • Insert the nuclear authorisation disk into slot.
      • -
      • Type numeric authorisation code into the keypad. This should have been provided. Note: If you make a mistake press R to reset the device. -
      • Press the E button to log onto the device.
      • - You now have activated the device. To deactivate the buttons at anytime for example when you've already prepped the bomb for detonation remove the auth disk OR press the R on the keypad.
        - Now the bomb CAN ONLY be detonated using the timer. Manual detonation is not an option.
        - Note: Nanotrasen is a pain in the neck.
        - Toggle off the SAFETY.
        - Note: You wouldn't believe how many Syndicate Operatives with doctorates have forgotten this step.
        - So use the - - and + + to set a det time between 5 seconds and 10 minutes.
        - Then press the timer toggle button to start the countdown.
        - Now remove the auth. disk so that the buttons deactivate.
        - Note: THE BOMB IS STILL SET AND WILL DETONATE
        - Now before you remove the disk if you need to move the bomb you can:
        - Toggle off the anchor, move it, and re-anchor.

        - Good luck. Remember the order:
        - Disk, Code, Safety, Timer, Disk, RUN!
        - Intelligence Analysts believe that normal Nanotrasen procedure is for the Captain to secure the nuclear authorisation disk.
        - Good luck! - "} + + + + +

        Nuclear Explosives 101

        + Hello and thank you for choosing the Syndicate for your nuclear information needs. Today's crash course will deal with the operation of a Fusion Class NanoTrasen made Nuclear Device.

        + + First and foremost, DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE. Pressing any button on the compacted bomb will cause it to extend and bolt itself into place. If this is done, to unbolt it, one must completely log in, which at this time may not be possible.
        + +

        To make the nuclear device functional

        +
          +
        • Place the nuclear device in the designated detonation zone.
        • +
        • Extend and anchor the nuclear device from its interface.
        • +
        • Insert the nuclear authorisation disk into the slot.
        • +
        • Type the numeric authorisation code into the keypad. This should have been provided.
          + Note: If you make a mistake, press R to reset the device. +
        • Press the E button to log on to the device.
        • +

        + + You now have activated the device. To deactivate the buttons at anytime, for example when you've already prepped the bomb for detonation, remove the authentication disk OR press R on the keypad.

        + Now the bomb CAN ONLY be detonated using the timer. Manual detonation is not an option. Toggle off the SAFETY.
        + Note: You wouldn't believe how many Syndicate Operatives with doctorates have forgotten this step.

        + + So use the - - and + + to set a detonation time between 5 seconds and 10 minutes. Then press the timer toggle button to start the countdown. Now remove the authentication disk so that the buttons deactivate.
        + Note: THE BOMB IS STILL SET AND WILL DETONATE

        + + Now before you remove the disk, if you need to move the bomb, you can toggle off the anchor, move it, and re-anchor.

        + + Remember the order:
        + Disk, Code, Safety, Timer, Disk, RUN!

        + Intelligence Analysts believe that normal NanoTrasen procedure is for the Captain to secure the nuclear authentication disk.

        + + Good luck! + + + "} /obj/item/weapon/book/manual/atmospipes name = "Pipes and You: Getting To Know Your Scary Tools" @@ -976,92 +1040,102 @@ -

        Contents

          -
        1. Author's Forward
        2. +
        3. Author's Foreword
        4. Basic Piping
        5. Insulated Pipes
        6. Atmospherics Devices
        7. Heat Exchange Systems
        8. Final Checks
        9. -
        -

        +
        -

        HOW TO NOT SUCK QUITE SO HARD AT ATMOSPHERICS


        +

        HOW TO NOT SUCK QUITE SO HARD AT ATMOSPHERICS


        Or: What the fuck does a "passive gate" do?

        Alright. It has come to my attention that a variety of people are unsure of what a "pipe" is and what it does. - Apparently there is an unnatural fear of these arcane devices and their "gases". Spooky, spooky. So, + Apparently, there is an unnatural fear of these arcane devices and their "gases." Spooky, spooky. So, this will tell you what every device constructable by an ordinary pipe dispenser within atmospherics actually does. You are not going to learn what to do with them to be the super best person ever, or how to play guitar with passive gates, or something like that. Just what stuff does.

        -

        Basic Pipes


        +

        Basic Pipes

        The boring ones.
        - TMost ordinary pipes are pretty straightforward. They hold gas. If gas is moving in a direction for some reason, gas will flow in that direction. + Most ordinary pipes are pretty straightforward. They hold gas. If gas is moving in a direction for some reason, gas will flow in that direction. That's about it. Even so, here's all of your wonderful pipe options.
        -
      • Straight pipes: They're pipes. One-meter sections. Straight line. Pretty simple. Just about every pipe and device is based around this +
          +
        • Straight pipes: They're pipes. One-meter sections. Straight line. Pretty simple. Just about every pipe and device is based around this standard one-meter size, so most things will take up as much space as one of these.
        • +
        • Bent pipes: Pipes with a 90 degree bend at the half-meter mark. My goodness.
        • +
        • Pipe manifolds: Pipes that are essentially a "T" shape, allowing you to connect three things at one point.
        • +
        • 4-way manifold: A four-way junction.
        • +
        • Pipe cap: Caps off the end of a pipe. Open ends don't actually vent air, because of the way the pipes are assembled, so, uh, use them to decorate your house or something.
        • +
        • Manual valve: A valve that will block off airflow when turned. Can't be used by the AI or cyborgs, because they don't have hands.
        • +
        • Manual T-valve: Like a manual valve, but at the center of a manifold instead of a straight pipe.


        • +
        + +

        Insulated Pipes

      • Bent pipes: Pipes with a 90 degree bend at the half-meter mark. My goodness.
      • Pipe manifolds: Pipes that are essentially a "T" shape, allowing you to connect three things at one point.
      • 4-way manifold: A four-way junction.
      • Pipe cap: Caps off the end of a pipe. Open ends don't actually vent air, because of the way the pipes are assembled, so, uh. Use them to decorate your house or something.
      • Manual Valve: A valve that will block off airflow when turned. Can't be used by the AI or cyborgs, because they don't have hands.
      • -<
      • Manual T-Valve: Like a manual valve, but at the center of a manifold instead of a straight pipe.


      • +
      • Manual T-Valve: Like a manual valve, but at the center of a manifold instead of a straight pipe.


      • Insulated Pipes


        Special Public Service Announcement.
        Our regular pipes are already insulated. These are completely worthless. Punch anyone who uses them.

        -

        Devices:


        +

        Devices:

        They actually do something.
        - This is usually where people get frightened,
        afraid, and start calling on their gods and/or cowering in fear. Yes, I can see you doing that right now. + This is usually where people get frightened, afraid, and start calling on their gods and/or cowering in fear. Yes, I can see you doing that right now. Stop it. It's unbecoming. Most of these are fairly straightforward.
        -
      • Gas Pump: Take a wild guess. It moves gas in the direction it's pointing (marked by the red line on one end). It moves it based on pressure, the maximum output being 4500 kPa (kilopascals). +
          +
        • Gas pump: Take a wild guess. It moves gas in the direction it's pointing (marked by the red line on one end). It moves it based on pressure, the maximum output being 4500 kPa (kilopascals). Ordinary atmospheric pressure, for comparison, is 101.3 kPa, and the minimum pressure of room-temperature pure oxygen needed to not suffocate in a matter of minutes is 16 kPa - (though 18 is preferred using internals, for various reasons).
        • -
        • Volume pump: This pump goes based on volume, instead of pressure, and the possible maximum pressure it can create in the pipe on the recieving end is double the gas pump because of this, + (though 18 kPa is preferred using internals, for various reasons).
        • +
        • Volume pump: This pump goes based on volume, instead of pressure, and the possible maximum pressure it can create in the pipe on the receiving end is double the gas pump because of this, clocking in at an incredible 9000 kPa. If a pipe with this is destroyed or damaged, and this pressure of gas escapes, it can be incredibly dangerous depending on the size of the pipe filled. Don't hook this to the distribution loop, or you will make babies cry and the Chief Engineer brutally beat you.
        • -
        • Passive gate: This is essentially a cap on the pressure of gas allowed to flow in a specific direction. +
        • Passive gate: This is essentially a cap on the pressure of gas allowed to flow in a specific direction. When turned on, instead of actively pumping gas, it measures the pressure flowing through it, and whatever pressure you set is the maximum: it'll cap after that. In addition, it only lets gas flow one way. The direction the gas flows is opposite the red handle on it, which is confusing to people used to the red stripe on pumps pointing the way.
        • -
        • Unary vent: The basic vent used in rooms. It pumps gas into the room, but can't suck it back out. Controlled by the room's air alarm system.
        • -
        • Scrubber: The other half of room equipment. Filters air, and can suck it in entirely in what's called a "panic siphon". Actvating a panic siphon without very good reason will kill someone. Don't do it.
        • -
        • Meter: A little box with some gagues and numbers. Fasten it to any pipe or manifold, and it'll read you the pressure in it. Very useful.
        • -
        • Gas mixer: Two sides are input, one side is output. Mixes the gases pumped into it at the ratio defined. The side perpendicular to the other two is "node 2", for reference. +
        • Unary vent: The basic vent used in rooms. It pumps gas into the room, but can't suck it back out. Controlled by the room's air alarm system.
        • +
        • Scrubber: The other half of room equipment. Filters air, and can suck it in entirely in what's called a "panic siphon." Activating a panic siphon without very good reason will kill someone. Don't do it.
        • +
        • Meter: A little box with some gauges and numbers. Fasten it to any pipe or manifold and it'll read you the pressure in it. Very useful.
        • +
        • Gas mixer: Two sides are input, one side is output. Mixes the gases pumped into it at the ratio defined. The side perpendicular to the other two is "node 2," for reference. Can output this gas at pressures from 0-4500 kPa.
        • -
        • Gas filter: Essentially the opposite of a gas mixer. One side is input. The other two sides are output. One gas type will be filtered into the perpendicular output pipe, +
        • Gas filter: Essentially the opposite of a gas mixer. One side is input. The other two sides are output. One gas type will be filtered into the perpendicular output pipe, the rest will continue out the other side. Can also output from 0-4500 kPa.
        • +
        -

        Heat Exchange Systems


        +

        Heat Exchange Systems

        Will not set you on fire.
        - These systems are used to transfer heat only between two pipes. They will not move gases or any other element, but will equalize the temperature (eventually). Note that because of how gases work (remember: pv=nRt), + These systems are used to only transfer heat between two pipes. They will not move gases or any other element, but will equalize the temperature (eventually). Note that because of how gases work (remember: pv=nRt), a higher temperature will raise pressure, and a lower one will lower temperature.
      • Pipe: This is a pipe that will exchange heat with the surrounding atmosphere. Place in fire for superheating. Place in space for supercooling.
      • -
      • Bent Pipe: Take a wild guess.
      • -
      • Junction:Junction:The point where you connect your normal pipes to heat exchange pipes. Not necessary for heat exchangers, but necessary for H/E pipes/bent pipes.
      • -
      • Heat Exchanger: These funky-looking bits attach to an open pipe end. Put another heat exchanger directly across from it, and you can transfer heat across two pipes without having to have the gases touch. +
      • Bent pipe: Take a wild guess.
      • +
      • Junction: The point where you connect your normal pipes to heat exchange pipes. Not necessary for heat exchangers, but necessary for H/E pipes/bent pipes.
      • +
      • Heat exchanger: These funky-looking bits attach to an open pipe end. Put another heat exchanger directly across from it, and you can transfer heat across two pipes without having to have the gases touch. This normally shouldn't exchange with the ambient air, despite being totally exposed. Just don't ask questions...

      • - - That's about it for pipes. Go forth, armed with this knowledge, and try not to break, burn down, or kill anything. Please.
        + That's about it for pipes. Go forth, armed with this knowledge, and try not to break, burn down, or kill anything. Please. - + "} /obj/item/weapon/book/manual/evaguide @@ -1073,62 +1147,64 @@ - -

        Contents

        +

        EVA Gear and You: Not Spending All Day Inside

        + Or: How not to suffocate because there's a hole in your shoes
        + +

        Contents

          -
        1. A forward on using EVA gear
        2. -
        3. Donning a Civilian Suits
        4. +
        5. A foreword on using EVA gear
        6. +
        7. Donning a Civilian Suit
        8. Putting on a Hardsuit
        9. Final Checks
        -

        - -

        EVA Gear and You: Not Spending All Day Inside


        - Or: How not to suffocate because there's a hole in your shoes

        +
        EVA gear. Wonderful to use. It's useful for mining, engineering, and occasionally just surviving, if things are that bad. Most people have EVA training, but apparently there are some on a space station who don't. This guide should give you a basic idea of how to use this gear, safely. It's split into two sections: Civilian suits and hardsuits.

        -

        Civilian Suits


        +

        Civilian Suits

        The bulkiest things this side of Alpha Centauri
        - These suits are the grey ones that are stored in EVA. They're the more simple to get on, but are also a lot bulkier, and provide less protection from environmental hazards such as radiaion or physical impact. + These suits are the grey ones that are stored in EVA. They're the more simple to get on, but are also a lot bulkier, and provide less protection from environmental hazards such as radiation or physical impact. As Medical, Engineering, Security, and Mining all have hardsuits of their own, these don't see much use, but knowing how to put them on is quite useful anyways.

        - First, take the suit. It should be in three pieces: A top, a bottom,
        and a helmet. Put the bottom on first, shoes and the like will fit in it. If you have magnetic boots, however, + First, take the suit. It should be in three pieces: A top, a bottom, and a helmet. Put the bottom on first, shoes and the like will fit in it. If you have magnetic boots, however, put them on on top of the suit's feet. Next, get the top on, as you would a shirt. It can be somewhat awkward putting these pieces on, due to the makeup of the suit, but to an extent they will adjust to you. You can then find the snaps and seals around the waist, where the two pieces meet. Fasten these, and double-check their tightness. The red indicators around the waist of the lower half will turn green when this is done correctly. Next, put on whatever breathing apparatus you're using, be it a gas mask or a breath mask. Make sure the oxygen tube is fastened into it. - Put on the helmet now, straight forward, and make sure the tube goes into the small opening specifically for internals. Again, fasten seals around the neck, a small indicator light in the inside of the helmet should go from red to off when all is fastened. - There is a small slot on the side of the suit where an emergency oxygen tank or extended emergency oxygen tank will fit, - but it is reccomended to have a full-sized tank on your back for EVA.

        + Put on the helmet now, straightforward, and make sure the tube goes into the small opening specifically for internals. Again, fasten seals around the neck, a small indicator light in the inside of the helmet should go from red to off when all is fastened. + There is a small slot on the side of the suit where an emergency oxygen tank or extended emergency oxygen tank will fit, + but it is recommended to have a full-sized tank on your back for EVA.

        -

        Hardsuits


        +

        Hardsuits

        Heavy, uncomfortable, still the best option.
        These suits come in Engineering, Mining, and the Armory. There's also a couple Medical Hardsuits in EVA. These provide a lot more protection than the standard suits.

        Similarly to the other suits, these are split into three parts. Fastening the pant and top are mostly the same as the other spacesuits, with the exception that these are a bit heavier, - though not as bulky. The helmet goes on differently, with the air tube feeing into the suit and out a hole near the left shoulder, while the helmet goes on turned ninety degrees counter-clockwise, + though not as bulky. The helmet goes on differently, with the air tube feeding into the suit and out a hole near the left shoulder, while the helmet goes on turned ninety degrees counter-clockwise, and then is screwed in for one and a quarter full rotations clockwise, leaving the faceplate directly in front of you. There is a small button on the right side of the helmet that activates the helmet light. - The tanks that fasten onto the side slot are emergency tanks, as
        well as full-sized oxygen tanks, leaving your back free for a backpack or satchel.

        + The tanks that fasten onto the side slot are emergency tanks, as well as full-sized oxygen tanks, leaving your back free for a backpack or satchel.

        -

        FINAL CHECKS:


        -
      • Are all seals fastened correctly?
      • -
      • Do you either have shoes on under the suit, or magnetic boots on over it?
      • -
      • Do you have a mask on and internals on the suit or your back?
      • -
      • Do you have a way to communicate with the station in case something goes wrong?
      • -
      • Do you have a second person watching if this is a training session?

      • +

        Final Checks

        +
          +
        • Are all seals fastened correctly?
        • +
        • Do you either have shoes on under the suit, or magnetic boots on over it?
        • +
        • Do you have a mask on and internals on the suit or your back?
        • +
        • Do you have a way to communicate with the station in case something goes wrong?
        • +
        • Do you have a second person watching if this is a training session?

        • +
        - If you don't have any further issues, go out and do whatever is necessary.
        + If you don't have any further issues, go out and do whatever is necessary. - + "} diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index 3be61531..03a6e599 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -15,9 +15,22 @@ max_combined_w_class = 21 /obj/item/weapon/storage/backpack/attackby(obj/item/weapon/W as obj, mob/user as mob) - playsound(src.loc, "rustle", 50, 1, -5) + if (src.use_sound) + playsound(src.loc, src.use_sound, 50, 1, -5) ..() +/obj/item/weapon/storage/backpack/equipped(var/mob/user, var/slot) + if (slot == slot_back && src.use_sound) + playsound(src.loc, src.use_sound, 50, 1, -5) + ..(user, slot) + +/* +/obj/item/weapon/storage/backpack/dropped(mob/user as mob) + if (loc == user && src.use_sound) + playsound(src.loc, src.use_sound, 50, 1, -5) + ..(user) +*/ + /* * Backpack Types */ diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index 562d9c19..281ab96d 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -94,7 +94,7 @@ storage_slots = 50; //the number of plant pieces it can carry. max_combined_w_class = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * plants.w_class max_w_class = 3 - w_class = 1 + w_class = 2 can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/grown","/obj/item/seeds","/obj/item/weapon/grown") @@ -252,5 +252,5 @@ storage_slots = 50; //the number of cash pieces it can carry. max_combined_w_class = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * cash.w_class max_w_class = 3 - w_class = 1 + w_class = 2 can_hold = list("/obj/item/weapon/coin","/obj/item/weapon/spacecash") diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 494a7642..b687b297 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -8,29 +8,6 @@ slot_flags = SLOT_BELT attack_verb = list("whipped", "lashed", "disciplined") - -/obj/item/weapon/storage/belt/proc/can_use() - return is_equipped() - - -/obj/item/weapon/storage/belt/MouseDrop(obj/over_object as obj, src_location, over_location) - var/mob/M = usr - if(!istype(over_object, /obj/screen)) - return ..() - playsound(src.loc, "rustle", 50, 1, -5) - if (!M.restrained() && !M.stat && can_use()) - switch(over_object.name) - if("r_hand") - M.u_equip(src) - M.put_in_r_hand(src) - if("l_hand") - M.u_equip(src) - M.put_in_l_hand(src) - src.add_fingerprint(usr) - return - - - /obj/item/weapon/storage/belt/utility name = "tool-belt" //Carn: utility belt is nicer, but it bamboozles the text parsing. desc = "Can hold various tools." @@ -159,12 +136,6 @@ "/obj/item/clothing/mask/luchador" ) -/obj/item/weapon/storage/belt/inflatable - name = "inflatable duck" - desc = "No bother to sink or swim when you can just float!" - icon_state = "inflatable" - item_state = "inflatable" - /obj/item/weapon/storage/belt/security/tactical name = "combat belt" desc = "Can hold security gear like handcuffs and flashes, with more pouches for more storage." diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm index a0b658a7..4bc5f68d 100644 --- a/code/game/objects/items/weapons/storage/bible.dm +++ b/code/game/objects/items/weapons/storage/bible.dm @@ -102,5 +102,6 @@ A.reagents.add_reagent("holywater",water2holy) /obj/item/weapon/storage/bible/attackby(obj/item/weapon/W as obj, mob/user as mob) - playsound(src.loc, "rustle", 50, 1, -5) + if (src.use_sound) + playsound(src.loc, src.use_sound, 50, 1, -5) ..() diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 60f945c5..00d2eafa 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -156,7 +156,19 @@ new /obj/item/ammo_casing/shotgun/blank(src) new /obj/item/ammo_casing/shotgun/blank(src) +/obj/item/weapon/storage/box/beanbags + name = "box of beanbag shells" + desc = "It has a picture of a gun and several warning symbols on the front.
        WARNING: Live ammunition. Misuse may result in serious injury or death." + New() + ..() + new /obj/item/ammo_casing/shotgun/beanbag(src) + new /obj/item/ammo_casing/shotgun/beanbag(src) + new /obj/item/ammo_casing/shotgun/beanbag(src) + new /obj/item/ammo_casing/shotgun/beanbag(src) + new /obj/item/ammo_casing/shotgun/beanbag(src) + new /obj/item/ammo_casing/shotgun/beanbag(src) + new /obj/item/ammo_casing/shotgun/beanbag(src) /obj/item/weapon/storage/box/flashbangs name = "box of flashbangs (WARNING)" @@ -185,7 +197,7 @@ new /obj/item/weapon/grenade/empgrenade(src) new /obj/item/weapon/grenade/empgrenade(src) new /obj/item/weapon/grenade/empgrenade(src) -// new /obj/item/device/flashlight/emp/(src)(src) Waiting on fix of the EMP Flashlight + new /obj/item/device/flashlight/emp/(src)//Waiting on fix of the EMP Flashlight /obj/item/weapon/storage/box/trackimp @@ -435,7 +447,7 @@ /obj/item/weapon/storage/box/matches name = "matchbox" - desc = "A small box of Almost But Not Quite Plasma Premium Matches." + desc = "A small box of 'Space-Proof' premium matches." icon = 'icons/obj/cigarettes.dmi' icon_state = "matchbox" item_state = "zippo" @@ -477,7 +489,7 @@ foldable = /obj/item/stack/sheet/cardboard //BubbleWrap storage_slots=21 can_hold = list("/obj/item/weapon/light/tube", "/obj/item/weapon/light/bulb") - max_combined_w_class = 21 + max_combined_w_class = 42 //holds 21 items of w_class 2 use_to_pickup = 1 // for picking up broken bulbs, not that most people will try /obj/item/weapon/storage/box/lights/bulbs/New() diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm index 065c0920..bb5c5b56 100644 --- a/code/game/objects/items/weapons/storage/briefcase.dm +++ b/code/game/objects/items/weapons/storage/briefcase.dm @@ -2,6 +2,7 @@ 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_state = "briefcase" + item_state = "briefcase" flags = FPRINT | TABLEPASS| CONDUCT force = 8.0 throw_speed = 1 diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index b1df60a8..1319e413 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -2,7 +2,6 @@ * Contains: * First Aid Kits * Pill Bottles - * Dice Pack (in a pill bottle) */ /* @@ -124,29 +123,7 @@ allow_quick_gather = 1 use_to_pickup = 1 storage_slots = 14 - -/obj/item/weapon/storage/pill_bottle/MouseDrop(obj/over_object as obj) //Quick pillbottle fix. -Agouri - - if (ishuman(usr) || ismonkey(usr)) //Can monkeys even place items in the pocket slots? Leaving this in just in case~ - var/mob/M = usr - if (!( istype(over_object, /obj/screen) )) - return ..() - if ((!( M.restrained() ) && !( M.stat ) /*&& M.pocket == src*/)) - switch(over_object.name) - if("r_hand") - M.u_equip(src) - M.put_in_r_hand(src) - if("l_hand") - M.u_equip(src) - M.put_in_l_hand(src) - src.add_fingerprint(usr) - return - if(over_object == usr && in_range(src, usr) || usr.contents.Find(src)) - if (usr.s_active) - usr.s_active.close(usr) - src.show_to(usr) - return - return + use_sound = null /obj/item/weapon/storage/pill_bottle/kelotane name = "bottle of kelotane pills" diff --git a/code/game/objects/items/weapons/storage/internal.dm b/code/game/objects/items/weapons/storage/internal.dm new file mode 100644 index 00000000..67205c76 --- /dev/null +++ b/code/game/objects/items/weapons/storage/internal.dm @@ -0,0 +1,85 @@ +//A storage item intended to be used by other items to provide storage functionality. +//Types that use this should consider overriding emp_act() and hear_talk(), unless they shield their contents somehow. +/obj/item/weapon/storage/internal + var/obj/item/master_item + +/obj/item/weapon/storage/internal/New(obj/item/MI) + master_item = MI + loc = master_item + name = master_item.name + verbs -= /obj/item/verb/verb_pickup //make sure this is never picked up. + ..() + +/obj/item/weapon/storage/internal/attack_hand() + return //make sure this is never picked up + +/obj/item/weapon/storage/internal/mob_can_equip() + return 0 //make sure this is never picked up + +//Helper procs to cleanly implement internal storages - storage items that provide inventory slots for other items. +//These procs are completely optional, it is up to the master item to decide when it's storage get's opened by calling open() +//However they are helpful for allowing the master item to pretend it is a storage item itself. +//If you are using these you will probably want to override attackby() as well. +//See /obj/item/clothing/suit/storage for an example. + +//items that use internal storage have the option of calling this to emulate default storage MouseDrop behaviour. +//returns 1 if the master item's parent's MouseDrop() should be called, 0 otherwise. It's strange, but no other way of +//doing it without the ability to call another proc's parent, really. +/obj/item/weapon/storage/internal/proc/handle_mousedrop(mob/user as mob, obj/over_object as obj) + if (ishuman(user) || ismonkey(user)) //so monkeys can take off their backpacks -- Urist + + if (istype(user.loc,/obj/mecha)) // stops inventory actions in a mech + return 0 + + if(over_object == user && Adjacent(user)) // this must come before the screen objects only block + src.open(user) + return 0 + + if (!( istype(over_object, /obj/screen) )) + return 1 + + //makes sure master_item is equipped before putting it in hand, so that we can't drag it into our hand from miles away. + //there's got to be a better way of doing this... + if (!(master_item.loc == user) || (master_item.loc && master_item.loc.loc == user)) + return 0 + + if (!( user.restrained() ) && !( user.stat )) + switch(over_object.name) + if("r_hand") + user.u_equip(master_item) + user.put_in_r_hand(master_item) + if("l_hand") + user.u_equip(master_item) + user.put_in_l_hand(master_item) + master_item.add_fingerprint(user) + return 0 + return 0 + +//items that use internal storage have the option of calling this to emulate default storage attack_hand behaviour. +//returns 1 if the master item's parent's attack_hand() should be called, 0 otherwise. +//It's strange, but no other way of doing it without the ability to call another proc's parent, really. +/obj/item/weapon/storage/internal/proc/handle_attack_hand(mob/user as mob) + + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.l_store == master_item && !H.get_active_hand()) //Prevents opening if it's in a pocket. + H.put_in_hands(master_item) + H.l_store = null + return 0 + if(H.r_store == master_item && !H.get_active_hand()) + H.put_in_hands(master_item) + H.r_store = null + return 0 + + src.add_fingerprint(user) + if (master_item.loc == user) + src.open(user) + return 0 + + for(var/mob/M in range(1, master_item.loc)) + if (M.s_active == src) + src.close(M) + return 1 + +/obj/item/weapon/storage/internal/Adjacent(var/atom/neighbor) + return master_item.Adjacent(neighbor) \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/misc.dm b/code/game/objects/items/weapons/storage/misc.dm new file mode 100644 index 00000000..1e798304 --- /dev/null +++ b/code/game/objects/items/weapons/storage/misc.dm @@ -0,0 +1,9 @@ + +/obj/item/weapon/storage/pill_bottle/dice + name = "pack of dice" + desc = "It's a small container with dice inside." + + New() + ..() + new /obj/item/weapon/dice( src ) + new /obj/item/weapon/dice/d20( src ) diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm index b2b5ecd7..e2504135 100644 --- a/code/game/objects/items/weapons/storage/secure.dm +++ b/code/game/objects/items/weapons/storage/secure.dm @@ -167,16 +167,12 @@ if ((src.loc == user) && (src.locked == 1)) usr << "\red [src] is locked and cannot be opened!" else if ((src.loc == user) && (!src.locked)) - playsound(src.loc, "rustle", 50, 1, -5) - if (user.s_active) - user.s_active.close(user) //Close and re-open - src.show_to(user) + src.open(usr) else ..() for(var/mob/M in range(1)) if (M.s_active == src) src.close(M) - src.orient2hud(user) src.add_fingerprint(user) return @@ -245,4 +241,4 @@ /obj/item/weapon/storage/secure/safe/HoS/New() ..() - //new /obj/item/weapon/storage/lockbox/clusterbang(src) This item is currently broken... and probably shouldnt exist to begin with (even though it's cool) \ No newline at end of file + //new /obj/item/weapon/storage/lockbox/clusterbang(src) This item is currently broken... and probably shouldnt exist to begin with (even though it's cool) diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 00d09353..ccb3ad30 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -22,41 +22,36 @@ var/allow_quick_gather //Set this variable to allow the object to have the 'toggle mode' verb, which quickly collects all items from a tile. var/collection_mode = 1; //0 = pick one at a time, 1 = pick all on tile var/foldable = null // BubbleWrap - if set, can be folded (when empty) into a sheet of cardboard + var/use_sound = "rustle" //sound played when used. null for no sound. /obj/item/weapon/storage/MouseDrop(obj/over_object as obj) if (ishuman(usr) || ismonkey(usr)) //so monkeys can take off their backpacks -- Urist - var/mob/M = usr if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech return - if(over_object == M && Adjacent(M)) // this must come before the screen objects only block - orient2hud(M) // dunno why it wasn't before - if(M.s_active) - M.s_active.close(M) - show_to(M) + if(over_object == usr && Adjacent(usr)) // this must come before the screen objects only block + src.open(usr) return if (!( istype(over_object, /obj/screen) )) return ..() + + //makes sure that the storage is equipped, so that we can't drag it into our hand from miles away. + //there's got to be a better way of doing this. if (!(src.loc == usr) || (src.loc && src.loc.loc == usr)) return - playsound(src.loc, "rustle", 50, 1, -5) - if (!( M.restrained() ) && !( M.stat )) + + if (!( usr.restrained() ) && !( usr.stat )) switch(over_object.name) if("r_hand") - M.u_equip(src) - M.put_in_r_hand(src) + usr.u_equip(src) + usr.put_in_r_hand(src) if("l_hand") - M.u_equip(src) - M.put_in_l_hand(src) + usr.u_equip(src) + usr.put_in_l_hand(src) src.add_fingerprint(usr) return - if(over_object == usr && in_range(src, usr) || usr.contents.Find(src)) - if (usr.s_active) - usr.s_active.close(usr) - src.show_to(usr) - return return @@ -101,6 +96,15 @@ user.s_active = null return +/obj/item/weapon/storage/proc/open(mob/user as mob) + if (src.use_sound) + playsound(src.loc, src.use_sound, 50, 1, -5) + + orient2hud(user) + if (user.s_active) + user.s_active.close(user) + show_to(user) + /obj/item/weapon/storage/proc/close(mob/user as mob) src.hide_from(user) @@ -313,17 +317,17 @@ if(isrobot(user)) user << "\blue You're a robot. No." - return 1 //Robots can't interact with storage items. + return //Robots can't interact with storage items. if(!can_be_inserted(W)) - return 0 + return if(istype(W, /obj/item/weapon/tray)) var/obj/item/weapon/tray/T = W if(T.calc_carry() > 0) if(prob(85)) user << "\red The tray won't fit in [src]." - return 1 + return else W.loc = user.loc if ((user.client && user.s_active != src)) @@ -331,15 +335,14 @@ W.dropped(user) user << "\red God damnit!" + W.add_fingerprint(user) handle_item_insertion(W) - return 1 + return /obj/item/weapon/storage/dropped(mob/user as mob) return /obj/item/weapon/storage/attack_hand(mob/user as mob) - playsound(src.loc, "rustle", 50, 1, -5) - if(ishuman(user)) var/mob/living/carbon/human/H = user if(H.l_store == src && !H.get_active_hand()) //Prevents opening if it's in a pocket. @@ -350,12 +353,9 @@ H.put_in_hands(src) H.r_store = null return - - src.orient2hud(user) + if (src.loc == user) - if (user.s_active) - user.s_active.close(user) - src.show_to(user) + src.open(user) else ..() for(var/mob/M in range(1)) @@ -455,4 +455,38 @@ var/obj/O = A O.hear_talk(M, text) - +//Returns the storage depth of an atom. This is the number of storage items the atom is contained in before reaching toplevel (the area). +//Returns -1 if the atom was not found on container. +/atom/proc/storage_depth(atom/container) + var/depth = 0 + var/atom/cur_atom = src + + while (cur_atom && !(cur_atom in container.contents)) + if (isarea(cur_atom)) + return -1 + if (istype(cur_atom.loc, /obj/item/weapon/storage)) + depth++ + cur_atom = cur_atom.loc + + if (!cur_atom) + return -1 //inside something with a null loc. + + return depth + +//Like storage depth, but returns the depth to the nearest turf +//Returns -1 if no top level turf (a loc was null somewhere, or a non-turf atom's loc was an area somehow). +/atom/proc/storage_depth_turf() + var/depth = 0 + var/atom/cur_atom = src + + while (cur_atom && !isturf(cur_atom)) + if (isarea(cur_atom)) + return -1 + if (istype(cur_atom.loc, /obj/item/weapon/storage)) + depth++ + cur_atom = cur_atom.loc + + if (!cur_atom) + return -1 //inside something with a null loc. + + return depth diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index bdae6e13..6f98f40d 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -117,6 +117,24 @@ new /obj/item/clothing/suit/space/syndicate(src) new /obj/item/clothing/head/helmet/space/syndicate(src) return +/obj/item/weapon/storage/box/syndie_kit/chameleon + name = "Chameleon Kit" + desc = "Comes with all the clothes you need to impersonate most people. Acting lessons sold seperately." + storage_slots = 10 + +/obj/item/weapon/storage/box/syndie_kit/chameleon/New() + ..() + new /obj/item/clothing/under/chameleon(src) + new /obj/item/clothing/head/chameleon(src) + new /obj/item/clothing/suit/chameleon(src) + new /obj/item/clothing/shoes/chameleon(src) + new /obj/item/weapon/storage/backpack/chameleon(src) + new /obj/item/clothing/gloves/chameleon(src) + new /obj/item/clothing/mask/chameleon(src) + new /obj/item/clothing/glasses/chameleon(src) + new /obj/item/weapon/gun/projectile/chameleon(src) + new /obj/item/ammo_magazine/chameleon(src) + return /obj/item/weapon/storage/box/syndie_kit/masks name = "boxed masquarade masks" diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index 416a0073..55e04456 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -357,6 +357,8 @@ if(istype(user, /mob/living/carbon/human)) var/mob/living/carbon/human/H = user var/datum/organ/internal/eyes/E = H.internal_organs["eyes"] + if(H.species.flags & IS_SYNTHETIC) + return switch(safety) if(1) usr << "\red Your eyes sting a little." @@ -447,22 +449,28 @@ item_state = "crowbar_red" /obj/item/weapon/weldingtool/attack(mob/M as mob, mob/user as mob) + if(hasorgans(M)) + var/datum/organ/external/S = M:organs_by_name[user.zone_sel.selecting] + if (!S) return if(!(S.status & ORGAN_ROBOT) || user.a_intent != "help") return ..() + + if(istype(M,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(H.species.flags & IS_SYNTHETIC) + if(M == user) + user << "\red You can't repair damage to your own body - it's against OH&S." + return + if(S.brute_dam) S.heal_damage(15,0,0,1) - if(user != M) - user.visible_message("\red \The [user] patches some dents on \the [M]'s [S.display_name] with \the [src]",\ - "\red You patch some dents on \the [M]'s [S.display_name]",\ - "You hear a welder.") - else - user.visible_message("\red \The [user] patches some dents on their [S.display_name] with \the [src]",\ - "\red You patch some dents on your [S.display_name]",\ - "You hear a welder.") + user.visible_message("\red \The [user] patches some dents on \the [M]'s [S.display_name] with \the [src].") + return else user << "Nothing to fix!" + else - return ..() + return ..() \ No newline at end of file diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 12f8c266..58bd7933 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -6,7 +6,7 @@ flags = FPRINT | TABLEPASS slot_flags = SLOT_BELT throwforce = 0 - w_class = 1.0 + w_class = 2.0 throw_speed = 7 throw_range = 15 attack_verb = list("banned") @@ -26,7 +26,7 @@ throw_speed = 1 throw_range = 4 throwforce = 10 - w_class = 1 + w_class = 2 suicide_act(mob/user) viewers(user) << "\red [user] is impaling \himself with the [src.name]! It looks like \he's trying to commit suicide." diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index f1d9265d..503df88a 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -14,7 +14,7 @@ LINEN BINS throwforce = 1 throw_speed = 1 throw_range = 2 - w_class = 1.0 + w_class = 2.0 item_color = "white" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm b/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm index 3e7d03f8..8fb8b0c9 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm @@ -40,7 +40,7 @@ shottas-- gun.icon_state = "projectile" -// gun.pixel_x = i*4 Trying some fixes to make the guncabinets less retarded -- Skull132 + gun.pixel_x = i*4 overlays += gun overlays += icon(src.icon,"door") diff --git a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm index 8c130dd0..3878d81d 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm @@ -95,3 +95,25 @@ else user << "\red Access Denied" return + +/obj/structure/closet/secure_closet/personal/verb/reset() + set src in oview(1) // One square distance + set category = "Object" + set name = "Reset Lock" + if(!usr.canmove || usr.stat || usr.restrained()) // Don't use it if you're not able to! Checks for stuns, ghost and restrain + return + if(ishuman(usr)) + src.add_fingerprint(usr) + if (src.locked || !src.registered_name) + usr << "\red You need to unlock it first." + else if (src.broken) + usr << "\red It appears to be broken." + else + if (src.opened) + if(!src.close()) + return + src.locked = 1 + src.icon_state = src.icon_locked + src.registered_name = null + src.desc = "It's a secure locker for personnel. The first card swiped gains control." + return \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm index e9bff51f..e22f31fc 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm @@ -15,7 +15,7 @@ //new /obj/item/clothing/suit/labcoat/science(src) new /obj/item/clothing/suit/storage/labcoat(src) new /obj/item/clothing/shoes/white(src) -// new /obj/item/weapon/cartridge/signal/toxins(src) +// new /obj/item/weapon/cartridge/signal/science(src) new /obj/item/device/radio/headset/headset_sci(src) new /obj/item/weapon/tank/air(src) new /obj/item/clothing/mask/gas(src) diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm index 45f3668b..1157d07b 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -227,8 +227,8 @@ return -/obj/structure/closet/wardrobe/toxins_white - name = "toxins wardrobe" +/obj/structure/closet/wardrobe/science_white + name = "science wardrobe" icon_state = "white" icon_closed = "white" diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index d4a368f6..82a8e425 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -93,7 +93,13 @@ return !density /obj/structure/grille/bullet_act(var/obj/item/projectile/Proj) + if(!Proj) return + + //Tasers and the like should not damage grilles. + if(Proj.damage_type == HALLOSS) + return + src.health -= Proj.damage*0.2 healthcheck() return 0 diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm new file mode 100644 index 00000000..a0a9a913 --- /dev/null +++ b/code/game/objects/structures/inflatable.dm @@ -0,0 +1,307 @@ +/obj/item/inflatable + name = "inflatable wall" + desc = "A folded membrane which rapidly expands into a large cubical shape on activation." + icon = 'icons/obj/inflatable.dmi' + icon_state = "folded_wall" + w_class = 3.0 + + attack_self(mob/user) + playsound(loc, 'sound/items/zip.ogg', 75, 1) + user << "\blue You inflate [src]." + var/obj/structure/inflatable/R = new /obj/structure/inflatable(user.loc) + src.transfer_fingerprints_to(R) + R.add_fingerprint(user) + del(src) + +/obj/structure/inflatable + name = "inflatable wall" + desc = "An inflated membrane. Do not puncture." + density = 1 + anchored = 1 + opacity = 0 + + icon = 'icons/obj/inflatable.dmi' + icon_state = "wall" + + var/health = 50.0 + + + New(location) + ..() + update_nearby_tiles(need_rebuild=1) + + Del() + update_nearby_tiles() + ..() + + proc/update_nearby_tiles(need_rebuild) //Copypasta from airlock code + if(!air_master) + return 0 + air_master.mark_for_update(get_turf(src)) + return 1 + + + + CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + return 0 + + bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + if(health <= 0) + deflate(1) + return + + + ex_act(severity) + switch(severity) + if(1.0) + del(src) + return + if(2.0) + deflate(1) + return + if(3.0) + if(prob(50)) + deflate(1) + return + + + blob_act() + deflate(1) + + + meteorhit() + //world << "glass at [x],[y],[z] Mhit" + deflate(1) + + attack_paw(mob/user as mob) + return attack_generic(user, 15) + + attack_hand(mob/user as mob) + add_fingerprint(user) + return + + + proc/attack_generic(mob/user as mob, damage = 0) //used by attack_alien, attack_animal, and attack_slime + health -= damage + if(health <= 0) + user.visible_message("[user] tears open [src]!") + deflate(1) + else //for nicer text~ + user.visible_message("[user] tears at [src]!") + + attack_alien(mob/user as mob) + if(islarva(user)) return + attack_generic(user, 15) + + attack_animal(mob/user as mob) + if(!isanimal(user)) return + var/mob/living/simple_animal/M = user + if(M.melee_damage_upper <= 0) return + attack_generic(M, M.melee_damage_upper) + + + attack_slime(mob/user as mob) + if(!isslimeadult(user)) return + attack_generic(user, rand(10, 15)) + + + attackby(obj/item/weapon/W as obj, mob/user as mob) + if(!istype(W)) return + + if (is_sharp(W)) + visible_message("\red [user] pierces [src] with [W]!") + deflate(1) + if(W.damtype == BRUTE || W.damtype == BURN) + hit(W.force) + ..() + return + + proc/hit(var/damage, var/sound_effect = 1) + health = max(0, health - damage) + if(sound_effect) + playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) + if(health <= 0) + deflate(1) + + + proc/deflate(var/violent=0) + playsound(loc, 'sound/machines/hiss.ogg', 75, 1) + if(violent) + visible_message("[src] rapidly deflates!") + var/obj/item/inflatable/torn/R = new /obj/item/inflatable/torn(loc) + src.transfer_fingerprints_to(R) + del(src) + else + //user << "\blue You slowly deflate the inflatable wall." + visible_message("[src] slowly deflates.") + spawn(50) + var/obj/item/inflatable/R = new /obj/item/inflatable(loc) + src.transfer_fingerprints_to(R) + del(src) + + verb/hand_deflate() + set name = "Deflate" + set category = "Object" + set src in oview(1) + + if(isobserver(usr)) //to stop ghosts from deflating + return + + deflate() + +/obj/item/inflatable/door/ + name = "inflatable door" + desc = "A folded membrane which rapidly expands into a simple door on activation." + icon = 'icons/obj/inflatable.dmi' + icon_state = "folded_door" + + attack_self(mob/user) + playsound(loc, 'sound/items/zip.ogg', 75, 1) + user << "\blue You inflate [src]." + var/obj/structure/inflatable/door/R = new /obj/structure/inflatable/door(user.loc) + src.transfer_fingerprints_to(R) + R.add_fingerprint(user) + del(src) + +/obj/structure/inflatable/door //Based on mineral door code + name = "inflatable door" + density = 1 + anchored = 1 + opacity = 0 + + icon = 'icons/obj/inflatable.dmi' + icon_state = "door_closed" + + var/state = 0 //closed, 1 == open + var/isSwitchingStates = 0 + + //Bumped(atom/user) + // ..() + // if(!state) + // return TryToSwitchState(user) + // return + + attack_ai(mob/user as mob) //those aren't machinery, they're just big fucking slabs of a mineral + if(isAI(user)) //so the AI can't open it + return + else if(isrobot(user)) //but cyborgs can + if(get_dist(user,src) <= 1) //not remotely though + return TryToSwitchState(user) + + attack_paw(mob/user as mob) + return TryToSwitchState(user) + + attack_hand(mob/user as mob) + return TryToSwitchState(user) + + CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group) + return state + if(istype(mover, /obj/effect/beam)) + return !opacity + return !density + + proc/TryToSwitchState(atom/user) + if(isSwitchingStates) return + if(ismob(user)) + var/mob/M = user + if(world.time - user.last_bumped <= 60) return //NOTE do we really need that? + if(M.client) + if(iscarbon(M)) + var/mob/living/carbon/C = M + if(!C.handcuffed) + SwitchState() + else + SwitchState() + else if(istype(user, /obj/mecha)) + SwitchState() + + proc/SwitchState() + if(state) + Close() + else + Open() + update_nearby_tiles() + + proc/Open() + isSwitchingStates = 1 + //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1) + flick("door_opening",src) + sleep(10) + density = 0 + opacity = 0 + state = 1 + update_icon() + isSwitchingStates = 0 + + proc/Close() + isSwitchingStates = 1 + //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1) + flick("door_closing",src) + sleep(10) + density = 1 + opacity = 0 + state = 0 + update_icon() + isSwitchingStates = 0 + + update_icon() + if(state) + icon_state = "door_open" + else + icon_state = "door_closed" + + deflate(var/violent=0) + playsound(loc, 'sound/machines/hiss.ogg', 75, 1) + if(violent) + visible_message("[src] rapidly deflates!") + var/obj/item/inflatable/door/torn/R = new /obj/item/inflatable/door/torn(loc) + src.transfer_fingerprints_to(R) + del(src) + else + //user << "\blue You slowly deflate the inflatable wall." + visible_message("[src] slowly deflates.") + spawn(50) + var/obj/item/inflatable/door/R = new /obj/item/inflatable/door(loc) + src.transfer_fingerprints_to(R) + del(src) + + +/obj/item/inflatable/torn + name = "torn inflatable wall" + desc = "A folded membrane which rapidly expands into a large cubical shape on activation. It is too torn to be usable." + icon = 'icons/obj/inflatable.dmi' + icon_state = "folded_wall_torn" + + attack_self(mob/user) + user << "\blue The inflatable wall is too torn to be inflated!" + add_fingerprint(user) + +/obj/item/inflatable/door/torn + name = "torn inflatable door" + desc = "A folded membrane which rapidly expands into a simple door on activation. It is too torn to be usable." + icon = 'icons/obj/inflatable.dmi' + icon_state = "folded_door_torn" + + attack_self(mob/user) + user << "\blue The inflatable door is too torn to be inflated!" + add_fingerprint(user) + +/obj/item/weapon/storage/briefcase/inflatable + name = "inflatable barrier box" + desc = "Contains inflatable walls and doors." + icon_state = "inf_box" + item_state = "syringe_kit" + max_combined_w_class = 21 + + New() + ..() + new /obj/item/inflatable/door(src) + new /obj/item/inflatable/door(src) + new /obj/item/inflatable/door(src) + new /obj/item/inflatable(src) + new /obj/item/inflatable(src) + new /obj/item/inflatable(src) + new /obj/item/inflatable(src) \ No newline at end of file diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm index 8209ca86..49a52da1 100644 --- a/code/game/objects/structures/musician.dm +++ b/code/game/objects/structures/musician.dm @@ -204,7 +204,11 @@ if("Cn9") soundfile = 'sound/piano/Cn9.ogg' else return - hearers(15, src) << sound(soundfile) + //hearers(15, src) << sound(soundfile) + var/turf/source = get_turf(src) + for(var/mob/M in hearers(15, source)) + M.playsound_local(source, file(soundfile), 100, falloff = 5) + /obj/structure/device/piano/proc/playsong() do diff --git a/code/game/objects/structures/transit_tubes.dm b/code/game/objects/structures/transit_tubes.dm index 8126296a..29bbed2e 100644 --- a/code/game/objects/structures/transit_tubes.dm +++ b/code/game/objects/structures/transit_tubes.dm @@ -117,12 +117,14 @@ obj/structure/ex_act(severity) /obj/structure/transit_tube/station/Bumped(mob/AM as mob|obj) if(!pod_moving && icon_state == "open" && istype(AM, /mob)) for(var/obj/structure/transit_tube_pod/pod in loc) - if(!pod.moving && pod.dir in directions()) + if(pod.contents.len) + AM << "" + return + else if(!pod.moving && pod.dir in directions()) AM.loc = pod return - - - + + /obj/structure/transit_tube/station/attack_hand(mob/user as mob) if(!pod_moving) for(var/obj/structure/transit_tube_pod/pod in loc) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 10aae5ca..88f6cc0f 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -18,6 +18,11 @@ /obj/structure/window/bullet_act(var/obj/item/projectile/Proj) + + //Tasers and the like should not damage windows. + if(Proj.damage_type == HALLOSS) + return + health -= Proj.damage ..() if(health <= 0) @@ -413,4 +418,17 @@ desc = "It looks rather strong and frosted over. Looks like it might take a few less hits then a normal reinforced window." icon_state = "fwindow" basestate = "fwindow" - health = 30 \ No newline at end of file + health = 30 + +/obj/structure/window/shuttle + name = "shuttle window" + desc = "It looks rather strong. Might take a few good hits to shatter it." + icon = 'icons/obj/podwindows.dmi' + icon_state = "window" + basestate = "window" + health = 40 + reinf = 1 + dir = 5 + + update_icon() //icon_state has to be set manually + return diff --git a/code/game/socket_talk.dm b/code/game/socket_talk.dm index b6024f3a..8484b636 100644 --- a/code/game/socket_talk.dm +++ b/code/game/socket_talk.dm @@ -23,4 +23,4 @@ return send_raw("type=keepalive") -var/global/datum/socket_talk/socket_talk \ No newline at end of file +var/global/datum/socket_talk/socket_talk diff --git a/code/game/sound.dm b/code/game/sound.dm index 2e55c983..6e0ba0dd 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -1,79 +1,41 @@ -/proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num) - //Frequency stuff only works with 45kbps oggs. +var/list/shatter_sound = list('sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg') +var/list/explosion_sound = list('sound/effects/Explosion1.ogg','sound/effects/Explosion2.ogg') +var/list/spark_sound = list('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks4.ogg') +var/list/rustle_sound = list('sound/effects/rustle1.ogg','sound/effects/rustle2.ogg','sound/effects/rustle3.ogg','sound/effects/rustle4.ogg','sound/effects/rustle5.ogg') +var/list/punch_sound = list('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg') +var/list/clown_sound = list('sound/effects/clownstep1.ogg','sound/effects/clownstep2.ogg') +var/list/swing_hit_sound = list('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg') +var/list/hiss_sound = list('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg') +var/list/page_sound = list('sound/effects/pageturn1.ogg', 'sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg') +//var/list/gun_sound = list('sound/weapons/Gunshot.ogg', 'sound/weapons/Gunshot2.ogg','sound/weapons/Gunshot3.ogg','sound/weapons/Gunshot4.ogg') - switch(soundin) - if ("shatter") soundin = pick('sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg') - if ("explosion") soundin = pick('sound/effects/Explosion1.ogg','sound/effects/Explosion2.ogg') - if ("sparks") soundin = pick('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks4.ogg') - if ("rustle") soundin = pick('sound/effects/rustle1.ogg','sound/effects/rustle2.ogg','sound/effects/rustle3.ogg','sound/effects/rustle4.ogg','sound/effects/rustle5.ogg') - if ("punch") soundin = pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg') - if ("clownstep") soundin = pick('sound/effects/clownstep1.ogg','sound/effects/clownstep2.ogg') - if ("swing_hit") soundin = pick('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg') - if ("hiss") soundin = pick('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg') - if ("pageturn") soundin = pick('sound/effects/pageturn1.ogg', 'sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg') +/proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num, falloff) - var/sound/S = sound(soundin) - S.wait = 0 //No queue - S.channel = 0 //Any channel - S.volume = vol + soundin = get_sfx(soundin) // same sound for everyone - if (vary) - S.frequency = rand(32000, 55000) + if(isarea(source)) + error("[source] is an area and is trying to make the sound: [soundin]") + return - for (var/A in range(world.view+extrarange, source)) // Plays for people in range. + var/frequency = get_rand_frequency() // Same frequency for everybody + var/turf/turf_source = get_turf(source) - if(ismob(A)) - var/mob/M = A - var/mob/M2 = locate(/mob/, M) - if (M2 && M2.client) - if(M2.ear_deaf <= 0 || !M.ear_deaf) - if(isturf(source)) - var/dx = source.x - M2.x - S.pan = max(-100, min(100, dx/8.0 * 100)) + // Looping through the player list has the added bonus of working for mobs inside containers + for (var/P in player_list) + var/mob/M = P + if(!M || !M.client) + continue + if(get_dist(M, turf_source) <= world.view + extrarange) + var/turf/T = get_turf(M) + if(T && T.z == turf_source.z) + M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff) - M2 << S +var/const/FALLOFF_SOUNDS = 1 +var/const/SURROUND_CAP = 7 - if (M.client) - if(M.ear_deaf <= 0 || !M.ear_deaf) - if(isturf(source)) - var/dx = source.x - M.x - S.pan = max(-100, min(100, dx/8.0 * 100)) - - M << S - - if(istype(A, /obj/structure/closet)) - var/obj/O = A - for(var/mob/M in O) - if (M.client) - if(M.ear_deaf <= 0 || !M.ear_deaf) - if(isturf(source)) - var/dx = source.x - M.x - S.pan = max(-100, min(100, dx/8.0 * 100)) - - M << S - - for(var/obj/mecha/mech in range(world.view+extrarange, source)) - var/mob/M = mech.occupant - if (M && M.client) - if(M.ear_deaf <= 0 || !M.ear_deaf) - if(isturf(source)) - var/dx = source.x - M.x - S.pan = max(-100, min(100, dx/8.0 * 100)) - - M << S - // Now plays for people in lockers! -- Polymorph - -/mob/proc/playsound_local(var/atom/source, soundin, vol as num, vary, extrarange as num) +/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff) if(!src.client || ear_deaf > 0) return - switch(soundin) - if ("shatter") soundin = pick('sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg') - if ("explosion") soundin = pick('sound/effects/Explosion1.ogg','sound/effects/Explosion2.ogg') - if ("sparks") soundin = pick('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks4.ogg') - if ("rustle") soundin = pick('sound/effects/rustle1.ogg','sound/effects/rustle2.ogg','sound/effects/rustle3.ogg','sound/effects/rustle4.ogg','sound/effects/rustle5.ogg') - if ("punch") soundin = pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg') - if ("clownstep") soundin = pick('sound/effects/clownstep1.ogg','sound/effects/clownstep2.ogg') - if ("swing_hit") soundin = pick('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg') - if ("hiss") soundin = pick('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg') + soundin = get_sfx(soundin) var/sound/S = sound(soundin) S.wait = 0 //No queue @@ -81,14 +43,46 @@ S.volume = vol if (vary) - S.frequency = rand(32000, 55000) - if(isturf(source)) - var/dx = source.x - src.x - S.pan = max(-100, min(100, dx/8.0 * 100)) + if(frequency) + S.frequency = frequency + else + S.frequency = get_rand_frequency() + + if(isturf(turf_source)) + // 3D sounds, the technology is here! + var/turf/T = get_turf(src) + var/dx = turf_source.x - T.x // Hearing from the right/left + + S.x = round(max(-SURROUND_CAP, min(SURROUND_CAP, dx)), 1) + + var/dz = turf_source.y - T.y // Hearing from infront/behind + S.z = round(max(-SURROUND_CAP, min(SURROUND_CAP, dz)), 1) + + // The y value is for above your head, but there is no ceiling in 2d spessmens. + S.y = 1 + S.falloff = (falloff ? falloff : FALLOFF_SOUNDS) src << S /client/proc/playtitlemusic() if(!ticker || !ticker.login_music) return if(prefs.toggles & SOUND_LOBBY) - src << sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = 1) // MAD JAMS \ No newline at end of file + src << sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = 1) // MAD JAMS + +/proc/get_rand_frequency() + return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs. + +/proc/get_sfx(soundin) + if(istext(soundin)) + switch(soundin) + if ("shatter") soundin = pick(shatter_sound) + if ("explosion") soundin = pick(explosion_sound) + if ("sparks") soundin = pick(spark_sound) + if ("rustle") soundin = pick(rustle_sound) + if ("punch") soundin = pick(punch_sound) + if ("clownstep") soundin = pick(clown_sound) + if ("swing_hit") soundin = pick(swing_hit_sound) + if ("hiss") soundin = pick(hiss_sound) + if ("pageturn") soundin = pick(page_sound) + //if ("gunshot") soundin = pick(gun_sound) + return soundin \ No newline at end of file diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index 6e84f822..4a2bcb39 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -37,8 +37,8 @@ var/list/mechtoys = list( //SUPPLY PACKS MOVED TO /code/defines/obj/supplypacks.dm /obj/structure/plasticflaps //HOW DO YOU CALL THOSE THINGS ANYWAY - name = "\improper Plastic flaps" - desc = "I definitely cant get past those. No way." + name = "\improper plastic flaps" + desc = "Completely impassable - or are they?" icon = 'icons/obj/stationobjs.dmi' //Change this. icon_state = "plasticflaps" density = 0 @@ -56,7 +56,7 @@ var/list/mechtoys = list( else if(istype(A, /mob/living)) // You Shall Not Pass! var/mob/living/M = A - if(!M.lying && !istype(M, /mob/living/carbon/monkey) && !istype(M, /mob/living/carbon/slime) && !istype(M, /mob/living/simple_animal/mouse)) //If your not laying down, or a small creature, no pass. + if(!M.lying && !istype(M, /mob/living/carbon/monkey) && !istype(M, /mob/living/carbon/slime) && !istype(M, /mob/living/simple_animal/mouse) && !istype(M, /mob/living/silicon/robot/drone)) //If your not laying down, or a small creature, no pass. return 0 return ..() @@ -497,36 +497,8 @@ var/list/mechtoys = list( user << "\blue Special supplies unlocked." hacked = 1 return - if(istype(I, /obj/item/weapon/screwdriver)) - playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, 20)) - if (stat & BROKEN) - user << "\blue The broken glass falls out." - var/obj/structure/computerframe/A = new /obj/structure/computerframe( loc ) - new /obj/item/weapon/shard( loc ) - var/obj/item/weapon/circuitboard/supplycomp/M = new /obj/item/weapon/circuitboard/supplycomp( A ) - for (var/obj/C in src) - C.loc = loc - A.circuit = M - A.state = 3 - A.icon_state = "3" - A.anchored = 1 - del(src) - else - user << "\blue You disconnect the monitor." - var/obj/structure/computerframe/A = new /obj/structure/computerframe( loc ) - var/obj/item/weapon/circuitboard/supplycomp/M = new /obj/item/weapon/circuitboard/supplycomp( A ) - if(can_order_contraband) - M.contraband_enabled = 1 - for (var/obj/C in src) - C.loc = loc - A.circuit = M - A.state = 4 - A.icon_state = "4" - A.anchored = 1 - del(src) else - attack_hand(user) + ..() return /obj/machinery/computer/supplycomp/Topic(href, href_list) diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index d6bd74c1..1d90122a 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -80,7 +80,7 @@ M.stop_pulling() step(M, M.dir) M << "\blue You slipped on the wet floor!" - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) M.Stun(5) M.Weaken(3) else @@ -91,7 +91,7 @@ M.stop_pulling() step(M, M.dir) M << "\blue You slipped on the wet floor!" - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) M.Stun(5) M.Weaken(3) else @@ -108,7 +108,7 @@ spawn(4) step(M, M.dir) M.take_organ_damage(2) // Was 5 -- TLE M << "\blue You slipped on the floor!" - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) M.Weaken(10) if(3) // Ice if(istype(M, /mob/living/carbon/human)) // Added check since monkeys don't have shoes @@ -116,7 +116,7 @@ M.stop_pulling() step(M, M.dir) M << "\blue You slipped on the icy floor!" - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) M.Stun(4) M.Weaken(3) else @@ -127,7 +127,7 @@ M.stop_pulling() step(M, M.dir) M << "\blue You slipped on the icy floor!" - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) M.Stun(4) M.Weaken(3) else diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 95c78102..b483e514 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -455,7 +455,7 @@ turf/simulated/floor/proc/update_icon() new floor_tile.type(src) make_plating() - playsound(src.loc, 'sound/items/Crowbar.ogg', 80, 1) + playsound(src, 'sound/items/Crowbar.ogg', 80, 1) return @@ -468,7 +468,7 @@ turf/simulated/floor/proc/update_icon() new floor_tile.type(src) make_plating() - playsound(src.loc, 'sound/items/Screwdriver.ogg', 80, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 80, 1) return @@ -479,7 +479,7 @@ turf/simulated/floor/proc/update_icon() user << "\blue Reinforcing the floor..." if(do_after(user, 30) && R && R.amount >= 2 && is_plating()) ChangeTurf(/turf/simulated/floor/engine) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 80, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 80, 1) R.use(2) return else @@ -512,7 +512,7 @@ turf/simulated/floor/proc/update_icon() T.use(1) update_icon() levelupdate() - playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) else user << "\blue This section is too damaged to support a tile. Use a welder to fix the damage." @@ -539,7 +539,7 @@ turf/simulated/floor/proc/update_icon() if(broken || burnt) if(welder.remove_fuel(0,user)) user << "\red You fix some dents on the broken plating." - playsound(src.loc, 'sound/items/Welder.ogg', 80, 1) + playsound(src, 'sound/items/Welder.ogg', 80, 1) icon_state = "plating" burnt = 0 broken = 0 diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm index e1e301d6..5a331b40 100644 --- a/code/game/turfs/simulated/floor_types.dm +++ b/code/game/turfs/simulated/floor_types.dm @@ -61,7 +61,7 @@ return if(istype(C, /obj/item/weapon/wrench)) user << "\blue Removing rods..." - playsound(src.loc, 'sound/items/Ratchet.ogg', 80, 1) + playsound(src, 'sound/items/Ratchet.ogg', 80, 1) if(do_after(user, 30)) new /obj/item/stack/rods(src, 2) ChangeTurf(/turf/simulated/floor) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 48722210..9e6f70d3 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -16,7 +16,7 @@ /turf/simulated/wall/proc/dismantle_wall(devastated=0, explode=0) if(istype(src,/turf/simulated/wall/r_wall)) if(!devastated) - playsound(src.loc, 'sound/items/Welder.ogg', 100, 1) + playsound(src, 'sound/items/Welder.ogg', 100, 1) new /obj/structure/girder/reinforced(src) new /obj/item/stack/sheet/plasteel( src ) else @@ -25,7 +25,7 @@ new /obj/item/stack/sheet/plasteel( src ) else if(istype(src,/turf/simulated/wall/cult)) if(!devastated) - playsound(src.loc, 'sound/items/Welder.ogg', 100, 1) + playsound(src, 'sound/items/Welder.ogg', 100, 1) new /obj/effect/decal/cleanable/blood(src) new /obj/structure/cultgirder(src) else @@ -34,7 +34,7 @@ else if(!devastated) - playsound(src.loc, 'sound/items/Welder.ogg', 100, 1) + playsound(src, 'sound/items/Welder.ogg', 100, 1) new /obj/structure/girder(src) if (mineral == "metal") new /obj/item/stack/sheet/metal( src ) @@ -138,7 +138,7 @@ return user << "\blue You push the wall but nothing happens!" - playsound(src.loc, 'sound/weapons/Genhit.ogg', 25, 1) + playsound(src, 'sound/weapons/Genhit.ogg', 25, 1) src.add_fingerprint(user) return @@ -156,7 +156,7 @@ var/obj/item/weapon/weldingtool/WT = W if( WT.remove_fuel(0,user) ) user << "You burn away the fungi with \the [WT]." - playsound(src.loc, 'sound/items/Welder.ogg', 10, 1) + playsound(src, 'sound/items/Welder.ogg', 10, 1) for(var/obj/effect/E in src) if(E.name == "Wallrot") del E rotting = 0 @@ -183,8 +183,8 @@ EB.spark_system.start() user << "You slash \the [src] with \the [EB]; the thermite ignites!" - playsound(src.loc, "sparks", 50, 1) - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) + playsound(src, "sparks", 50, 1) + playsound(src, 'sound/weapons/blade1.ogg', 50, 1) thermitemelt(user) return @@ -196,7 +196,7 @@ var/obj/item/weapon/weldingtool/WT = W if( WT.remove_fuel(0,user) ) user << "You begin slicing through the outer plating." - playsound(src.loc, 'sound/items/Welder.ogg', 100, 1) + playsound(src, 'sound/items/Welder.ogg', 100, 1) sleep(100) if( !istype(src, /turf/simulated/wall) || !user || !WT || !WT.isOn() || !T ) return @@ -211,7 +211,7 @@ else if( istype(W, /obj/item/weapon/pickaxe/plasmacutter) ) user << "You begin slicing through the outer plating." - playsound(src.loc, 'sound/items/Welder.ogg', 100, 1) + playsound(src, 'sound/items/Welder.ogg', 100, 1) sleep(60) if(mineral == "diamond")//Oh look, it's tougher @@ -247,7 +247,7 @@ EB.spark_system.start() user << "You stab \the [EB] into the wall and begin to slice it apart." - playsound(src.loc, "sparks", 50, 1) + playsound(src, "sparks", 50, 1) sleep(70) if(mineral == "diamond") @@ -256,8 +256,8 @@ if( user.loc == T && user.get_active_hand() == W ) EB.spark_system.start() - playsound(src.loc, "sparks", 50, 1) - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) + playsound(src, "sparks", 50, 1) + playsound(src, 'sound/weapons/blade1.ogg', 50, 1) dismantle_wall(1) for(var/mob/O in viewers(user, 5)) O.show_message("The wall was sliced apart by [user]!", 1, "You hear metal being sliced apart and sparks flying.", 2) diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index edee2567..822b4e77 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -25,7 +25,7 @@ return user << "\blue You push the wall but nothing happens!" - playsound(src.loc, 'sound/weapons/Genhit.ogg', 25, 1) + playsound(src, 'sound/weapons/Genhit.ogg', 25, 1) src.add_fingerprint(user) return @@ -44,7 +44,7 @@ var/obj/item/weapon/weldingtool/WT = W if( WT.remove_fuel(0,user) ) user << "You burn away the fungi with \the [WT]." - playsound(src.loc, 'sound/items/Welder.ogg', 10, 1) + playsound(src, 'sound/items/Welder.ogg', 10, 1) for(var/obj/effect/E in src) if(E.name == "Wallrot") del E rotting = 0 @@ -71,8 +71,8 @@ EB.spark_system.start() user << "You slash \the [src] with \the [EB]; the thermite ignites!" - playsound(src.loc, "sparks", 50, 1) - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) + playsound(src, "sparks", 50, 1) + playsound(src, 'sound/weapons/blade1.ogg', 50, 1) thermitemelt(user) return @@ -87,7 +87,7 @@ switch(d_state) if(0) if (istype(W, /obj/item/weapon/wirecutters)) - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 100, 1) src.d_state = 1 src.icon_state = "r_wall-1" new /obj/item/stack/rods( src ) @@ -97,7 +97,7 @@ if(1) if (istype(W, /obj/item/weapon/screwdriver)) user << "You begin removing the support lines." - playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) sleep(40) if( !istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T ) return @@ -127,7 +127,7 @@ if( WT.remove_fuel(0,user) ) user << "You begin slicing through the metal cover." - playsound(src.loc, 'sound/items/Welder.ogg', 100, 1) + playsound(src, 'sound/items/Welder.ogg', 100, 1) sleep(60) if( !istype(src, /turf/simulated/wall/r_wall) || !user || !WT || !WT.isOn() || !T ) return @@ -143,7 +143,7 @@ if( istype(W, /obj/item/weapon/pickaxe/plasmacutter) ) user << "You begin slicing through the metal cover." - playsound(src.loc, 'sound/items/Welder.ogg', 100, 1) + playsound(src, 'sound/items/Welder.ogg', 100, 1) sleep(40) if( !istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T ) return @@ -158,7 +158,7 @@ if (istype(W, /obj/item/weapon/crowbar)) user << "You struggle to pry off the cover." - playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) sleep(100) if( !istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T ) return @@ -173,7 +173,7 @@ if (istype(W, /obj/item/weapon/wrench)) user << "You start loosening the anchoring bolts which secure the support rods to their frame." - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) sleep(40) if( !istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T ) return @@ -190,7 +190,7 @@ if( WT.remove_fuel(0,user) ) user << "You begin slicing through the support rods." - playsound(src.loc, 'sound/items/Welder.ogg', 100, 1) + playsound(src, 'sound/items/Welder.ogg', 100, 1) sleep(100) if( !istype(src, /turf/simulated/wall/r_wall) || !user || !WT || !WT.isOn() || !T ) return @@ -207,7 +207,7 @@ if( istype(W, /obj/item/weapon/pickaxe/plasmacutter) ) user << "You begin slicing through the support rods." - playsound(src.loc, 'sound/items/Welder.ogg', 100, 1) + playsound(src, 'sound/items/Welder.ogg', 100, 1) sleep(70) if( !istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T ) return @@ -223,7 +223,7 @@ if( istype(W, /obj/item/weapon/crowbar) ) user << "You struggle to pry off the outer sheath." - playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) sleep(100) if( !istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T ) return diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index 82a8ff6d..1d85dce3 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -39,7 +39,7 @@ return var/obj/item/stack/rods/R = C user << "\blue Constructing support lattice ..." - playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) ReplaceWithLattice() R.use(1) return @@ -49,7 +49,7 @@ if(L) var/obj/item/stack/tile/plasteel/S = C del(L) - playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) S.build(src) S.use(1) return diff --git a/code/game/verbs/who.dm b/code/game/verbs/who.dm index cad74466..6450ba49 100644 --- a/code/game/verbs/who.dm +++ b/code/game/verbs/who.dm @@ -7,7 +7,7 @@ var/list/Lines = list() - if(holder) + if(holder && (R_ADMIN & holder.rights || R_MOD & holder.rights)) for(var/client/C in clients) var/entry = "\t[C.key]" if(C.holder && C.holder.fakekey) @@ -48,14 +48,15 @@ var/msg = "" var/modmsg = "" - var/custommsg = "" var/num_mods_online = 0 var/num_admins_online = 0 - var/num_custom_online = 0 - if(holder) for(var/client/C in admins) - if(R_ADMIN & C.holder.rights) + if(R_ADMIN & C.holder.rights || (!R_MOD & C.holder.rights)) //Used to determine who shows up in admin rows + + if(C.holder.fakekey && (!R_ADMIN & holder.rights && !R_MOD & holder.rights)) //Mentors can't see stealthmins + continue + msg += "\t[C] is a [C.holder.rank]" if(C.holder.fakekey) @@ -88,33 +89,15 @@ modmsg += "\n" num_mods_online++ - else - custommsg += "\t[C] is a [C.holder.rank]" - - if(isobserver(C.mob)) - custommsg += " - Observing" - else if(istype(C.mob,/mob/new_player)) - custommsg += " - Lobby" - else - custommsg += " - Playing" - - if(C.is_afk()) - custommsg += " (AFK)" - custommsg += "\n" - num_custom_online++ - else for(var/client/C in admins) - if(R_ADMIN & C.holder.rights) + if(R_ADMIN & C.holder.rights || (!R_MOD & C.holder.rights)) if(!C.holder.fakekey) msg += "\t[C] is a [C.holder.rank]\n" num_admins_online++ - else if(R_MOD & C.holder.rights) + else if (R_MOD & C.holder.rights) modmsg += "\t[C] is a [C.holder.rank]\n" num_mods_online++ - else - custommsg += "\t[C] is a [C.holder.rank]\n" - num_custom_online++ - msg = "Current Admins ([num_admins_online]):\n" + msg + "\n Current Moderators([num_mods_online]):\n" + modmsg + "\n Current Custom Ranks([num_custom_online]):\n" + custommsg + msg = "Current Admins ([num_admins_online]):\n" + msg + "\n Current Moderators([num_mods_online]):\n" + modmsg src << msg \ No newline at end of file diff --git a/code/global.dm b/code/global.dm index 1bb18ada..2090f5ef 100644 --- a/code/global.dm +++ b/code/global.dm @@ -116,7 +116,8 @@ var/list/reg_dna = list( ) var/mouse_respawn_time = 5 //Amount of time that must pass between a player dying as a mouse and repawning as a mouse. In minutes. -var/CELLRATE = 0.002 // multiplier for watts per tick <> cell storage (eg: 0.02 means if there is a load of 1000 watts, 20 units will be taken from a cell per second) +var/CELLRATE = 0.002 // multiplier for watts per tick <> cell storage (eg: 0.02 means if there is a load of 1000 watts, 20 units will be taken from a cell per second) + //It's a conversion constant. power_used*CELLRATE = charge_provided, or charge_used/CELLRATE = power_provided var/CHARGELEVEL = 0.0005 // Cap for how fast cells charge, as a percentage-per-tick (0.01 means cellcharge is capped to 1% per second) var/shuttle_z = 2 //default diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 8dbaf20b..ddce5cca 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -275,7 +275,7 @@ var/global/floorIsLava = 0 I.rank = "N/A" update_file = 1 dat += "[I.content] by [I.author] ([I.rank]) on [I.timestamp] " - if(I.author == usr.key) + if(I.author == usr.key || I.author == "Adminbot") dat += "Remove" dat += "

        " if(update_file) info << infos @@ -1114,6 +1114,30 @@ var/global/floorIsLava = 0 if(istype(H)) H.regenerate_icons() +proc/get_options_bar(whom, detail = 2, name = 0, link = 1) + if(!whom) + return "(*null*)" + var/mob/M + var/client/C + if(istype(whom, /client)) + C = whom + M = C.mob + else if(istype(whom, /mob)) + M = whom + C = M.client + else + return "(*not an mob*)" + switch(detail) + if(0) + return "[key_name(C, link, name)]" + if(1) + return "[key_name(C, link, name)](?)" + if(2) + var/ref_mob = "\ref[M]" + return "[key_name(C, link, name)](?) (PP) (VV) (SM) (JMP) (CA)" + + + // // //ALL DONE diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 2247d315..839ec18c 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -6,7 +6,8 @@ var/list/admin_verbs_default = list( /client/proc/hide_verbs, /*hides all our adminverbs*/ /client/proc/hide_most_verbs, /*hides all our hideable adminverbs*/ /client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/ - /client/proc/check_antagonists /*shows all antags*/ + /client/proc/check_antagonists, /*shows all antags*/ + /client/proc/cmd_mentor_check_new_players // /client/proc/deadchat /*toggles deadchat on/off*/ ) var/list/admin_verbs_admin = list( @@ -69,6 +70,7 @@ var/list/admin_verbs_admin = list( /client/proc/toggleattacklogs, /client/proc/toggledebuglogs, /client/proc/toggleghostwriters, + /client/proc/toggledrones, /datum/admins/proc/show_skills, /client/proc/check_customitem_activity, /client/proc/man_up, @@ -275,6 +277,8 @@ var/list/admin_verbs_mod = list( /client/proc/player_panel_new, /client/proc/dsay, /datum/admins/proc/show_skills, + /datum/admins/proc/show_player_panel, + /client/proc/check_antagonists, /client/proc/jobbans, /client/proc/cmd_admin_subtle_message /*send an message to somebody as a 'voice in their head'*/ ) @@ -566,24 +570,62 @@ var/list/admin_verbs_mod = list( set category = "Fun" set name = "Give Spell" set desc = "Gives a spell to a mob." - var/obj/effect/proc_holder/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spells + var/list/spell_names = list() + for(var/v in spells) + // "/obj/effect/proc_holder/spell/" 30 symbols ~Intercross21 + spell_names.Add(copytext("[v]", 31, 0)) + var/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spell_names if(!S) return - T.spell_list += new S + var/path = text2path("/obj/effect/proc_holder/spell/[S]") + T.spell_list += new path feedback_add_details("admin_verb","GS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! log_admin("[key_name(usr)] gave [key_name(T)] the spell [S].") message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] the spell [S].", 1) /client/proc/give_disease(mob/T as mob in mob_list) // -- Giacom set category = "Fun" - set name = "Give Disease" - set desc = "Gives a Disease to a mob." - var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in diseases + set name = "Give Disease (old)" + set desc = "Gives a (tg-style) Disease to a mob." + var/list/disease_names = list() + for(var/v in diseases) + // "/datum/disease/" 15 symbols ~Intercross + disease_names.Add(copytext("[v]", 16, 0)) + var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in disease_names if(!D) return - T.contract_disease(new D, 1) + var/path = text2path("/datum/disease/[D]") + T.contract_disease(new path, 1) feedback_add_details("admin_verb","GD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! log_admin("[key_name(usr)] gave [key_name(T)] the disease [D].") message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] the disease [D].", 1) +/client/proc/give_disease2(mob/T as mob in mob_list) // -- Giacom + set category = "Fun" + set name = "Give Disease" + set desc = "Gives a Disease to a mob." + + var/datum/disease2/disease/D = new /datum/disease2/disease() + + var/greater = ((input("Is this a lesser or greater disease?", "Give Disease") in list("Lesser", "Greater")) == "Greater") + + D.makerandom(greater) + if (!greater) + D.infectionchance = 1 + + D.infectionchance = input("How virulent is this disease? (1-100)", "Give Disease", D.infectionchance) as num + + if(istype(T,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = T + if (H.species) + D.affected_species = list(H.species.name) + if(istype(T,/mob/living/carbon/monkey)) + var/mob/living/carbon/monkey/M = T + D.affected_species = list(M.greaterform) + infect_virus2(T,D,1) + + feedback_add_details("admin_verb","GD2") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + log_admin("[key_name(usr)] gave [key_name(T)] a [(greater)? "greater":"lesser"] disease2 with infection chance [D.infectionchance].") + message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] a [(greater)? "greater":"lesser"] disease2 with infection chance [D.infectionchance].", 1) + /client/proc/make_sound(var/obj/O in world) // -- TLE set category = "Special Verbs" set name = "Make Sound" @@ -702,6 +744,12 @@ var/list/admin_verbs_mod = list( M.g_eyes = hex2num(copytext(new_eyes, 4, 6)) M.b_eyes = hex2num(copytext(new_eyes, 6, 8)) + var/new_skin = input("Please select body color. This is for Tajaran, Unathi, and Skrell only!", "Character Generation") as color + if(new_skin) + M.r_skin = hex2num(copytext(new_skin, 2, 4)) + M.g_skin = hex2num(copytext(new_skin, 4, 6)) + M.b_skin = hex2num(copytext(new_skin, 6, 8)) + var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation") as text if (new_tone) @@ -776,6 +824,19 @@ var/list/admin_verbs_mod = list( src << "Enabled ghost writers." message_admins("Admin [key_name_admin(usr)] has enabled ghost writers.", 1) +/client/proc/toggledrones() + set name = "Toggle maintenance drones" + set category = "Server" + if(!holder) return + if(config) + if(config.allow_drone_spawn) + config.allow_drone_spawn = 0 + src << "Disallowed maint drones." + message_admins("Admin [key_name_admin(usr)] has disabled maint drones.", 1) + else + config.allow_drone_spawn = 1 + src << "Enabled maint drones." + message_admins("Admin [key_name_admin(usr)] has enabled maint drones.", 1) /client/proc/toggledebuglogs() set name = "Toggle Debug Log Messages" diff --git a/code/modules/admin/create_object.dm b/code/modules/admin/create_object.dm index 54c67aa1..651e9a55 100644 --- a/code/modules/admin/create_object.dm +++ b/code/modules/admin/create_object.dm @@ -15,8 +15,9 @@ var/quick_create_object_html = null var/pathtext = null - pathtext = input("Select the path of the object you wish to create.", "Path", "/obj") in list("/obj","/obj/structure","/obj/item","/obj/item/weapon","/obj/machinery") - + pathtext = input("Select the path of the object you wish to create.", "Path", "/obj") as null|anything in list("/obj","/obj/structure","/obj/item","/obj/item/weapon","/obj/item/clothing","/obj/machinery","/obj/mecha") + if(!pathtext) + return var path = text2path(pathtext) if (!quick_create_object_html) diff --git a/code/modules/admin/player_notes.dm b/code/modules/admin/player_notes.dm index dd0f69b8..3a74da5f 100644 --- a/code/modules/admin/player_notes.dm +++ b/code/modules/admin/player_notes.dm @@ -152,3 +152,16 @@ datum/admins/proc/notes_gethtml(var/ckey) log_admin("[key_name(usr)] deleted one of [key]'s notes.") del info + +/proc/show_player_info_irc(var/key as text) + var/dat = " Info on [key]%0D%0A" + var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav") + var/list/infos + info >> infos + if(!infos) + dat = "No information found on the given key." + else + for(var/datum/player_info/I in infos) + dat += "[I.content]%0D%0Aby [I.author] ([I.rank]) on [I.timestamp]%0D%0A%0D%0A" + + return dat diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index a539beea..2f6d1f81 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -18,6 +18,8 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," if(src.handle_spam_prevention(msg,MUTE_ADMINHELP)) return + adminhelped = 1 //Determines if they get the message to reply by clicking the name. + /**src.verbs -= /client/verb/adminhelp spawn(1200) @@ -31,6 +33,8 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," if(!msg) return var/original_msg = msg + + //explode the input msg into a list var/list/msglist = text2list(msg, " ") @@ -87,7 +91,7 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," if(!mob) return //this doesn't happen var/ref_mob = "\ref[mob]" - msg = "\blue HELP: [key_name(src, 1)] (?) (PP) (VV) (SM) (JMP) (CA) [ai_found ? " (CL)" : ""]: [msg]" + msg = "\blue HELP: [get_options_bar(mob, 2, 1, 1)][ai_found ? " (CL)" : ""]: [msg]" //send this msg to all admins var/admin_number_afk = 0 diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 8e3f5e29..8eda6f8b 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -35,7 +35,8 @@ //takes input from cmd_admin_pm_context, cmd_admin_pm_panel or /client/Topic and sends them a PM. //Fetching a message if needed. src is the sender and C is the target client -/client/proc/cmd_admin_pm(var/client/C, var/msg) + +/client/proc/cmd_admin_pm(var/client/C, var/msg = null) if(prefs.muted & MUTE_ADMINHELP) src << "Error: Private-Message: You are unable to use PM-s (muted)." return @@ -45,14 +46,6 @@ else adminhelp(msg) //admin we are replying to left. adminhelp instead return - /*if(C && C.last_pm_recieved + config.simultaneous_pm_warning_timeout > world.time && holder) - //send a warning to admins, but have a delay popup for mods - if(holder.rights & R_ADMIN) - src << "\red Simultaneous PMs warning: that player has been PM'd in the last [config.simultaneous_pm_warning_timeout / 10] seconds by: [C.ckey_last_pm]" - else - if(alert("That player has been PM'd in the last [config.simultaneous_pm_warning_timeout / 10] seconds by: [C.ckey_last_pm]","Simultaneous PMs warning","Continue","Cancel") == "Cancel") - return*/ - //get message text, limit it's length.and clean/escape html if(!msg) msg = input(src,"Message:", "Private message to [key_name(C, 0, holder ? 1 : 0)]") as text|null @@ -85,7 +78,10 @@ else recieve_color = "maroon" send_pm_type = holder.rank + " " - recieve_pm_type = holder.rank + if(!C.holder && holder && holder.fakekey) + recieve_pm_type = "Admin" + else + recieve_pm_type = holder.rank else if(!C.holder) src << "Error: Admin-PM: Non-admin to non-admin PM communication is forbidden." @@ -94,7 +90,10 @@ var/recieve_message = "" if(holder && !C.holder) - recieve_message = "-- Administrator private message --\n" + recieve_message = "-- Click the [recieve_pm_type]'s name to reply --\n" + if(C.adminhelped) + C << recieve_message + C.adminhelped = 0 //AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn if(config.popup_admin_pm) @@ -109,7 +108,7 @@ adminhelp(reply) //sender has left, adminhelp instead return - recieve_message = "[recieve_pm_type] PM from-[key_name(src, C, C.holder ? 1 : 0)]: [msg]" + recieve_message = "[recieve_pm_type] PM from-[get_options_bar(src, C.holder ? 1 : 0, C.holder ? 1 : 0, 1)]: [msg]" C << recieve_message src << "[send_pm_type]PM to-[key_name(C, src, holder ? 1 : 0)]: [msg]" @@ -122,57 +121,6 @@ if(C.prefs.toggles & SOUND_ADMINHELP) C << 'sound/effects/adminhelp.ogg' - /* - if(C.holder) - if(holder) //both are admins - if(holder.rank == "Moderator") //If moderator - C << "Mod PM from-[key_name(src, C, 1)]: [msg]" - src << "Mod PM to-[key_name(C, src, 1)]: [msg]" - else - C << "Admin PM from-[key_name(src, C, 1)]: [msg]" - src << "Admin PM to-[key_name(C, src, 1)]: [msg]" - - else //recipient is an admin but sender is not - C << "Reply PM from-[key_name(src, C, 1)]: [msg]" - src << "PM to-Admins: [msg]" - - //play the recieving admin the adminhelp sound (if they have them enabled) - if(C.prefs.toggles & SOUND_ADMINHELP) - C << 'sound/effects/adminhelp.ogg' - - else - if(holder) //sender is an admin but recipient is not. Do BIG RED TEXT - if(holder.rank == "Moderator") - C << "Mod PM from-[key_name(src, C, 0)]: [msg]" - C << "Click on the moderators's name to reply." - src << "Mod PM to-[key_name(C, src, 1)]: [msg]" - else - C << "-- Administrator private message --" - C << "Admin PM from-[key_name(src, C, 0)]: [msg]" - C << "Click on the administrator's name to reply." - src << "Admin PM to-[key_name(C, src, 1)]: [msg]" - - //always play non-admin recipients the adminhelp sound - C << 'sound/effects/adminhelp.ogg' - - //AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn - if(config.popup_admin_pm) - spawn() //so we don't hold the caller proc up - var/sender = src - var/sendername = key - var/reply = input(C, msg,"Admin PM from-[sendername]", "") as text|null //show message and await a reply - if(C && reply) - if(sender) - C.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them - else - adminhelp(reply) //sender has left, adminhelp instead - return - - else //neither are admins - src << "Error: Admin-PM: Non-admin to non-admin PM communication is forbidden." - return - */ - log_admin("PM: [key_name(src)]->[key_name(C)]: [msg]") //we don't use message_admins here because the sender/receiver might get it too @@ -182,3 +130,32 @@ continue if(X.key!=key && X.key!=C.key && (X.holder.rights & R_ADMIN) || (X.holder.rights & R_MOD) ) X << "PM: [key_name(src, X, 0)]->[key_name(C, X, 0)]: \blue [msg]" //inform X + +/client/proc/cmd_admin_irc_pm() + if(prefs.muted & MUTE_ADMINHELP) + src << "Error: Private-Message: You are unable to use PM-s (muted)." + return + + var/msg = input(src,"Message:", "Private message to admins on IRC / 400 character limit") as text|null + + if(!msg) + return + + sanitize(msg) + + if(length(msg) > 400) // TODO: if message length is over 400, divide it up into seperate messages, the message length restriction is based on IRC limitations. Probably easier to do this on the bots ends. + src << "\red Your message was not sent because it was more then 400 characters find your message below for ease of copy/pasting" + src << "\blue [msg]" + return + + send2adminirc("PlayerPM from [key_name(src)]: [html_decode(msg)]") + + src << "IRC PM to-IRC-Admins: [msg]" + + log_admin("PM: [key_name(src)]->IRC: [msg]") + for(var/client/X in admins) + if(X == src) + continue + if((X.holder.rights & R_ADMIN) || (X.holder.rights & R_MOD)) + X << "PM: [key_name(src, X, 0)]->IRC-Admins: \blue [msg]" + diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm index b73a54d1..6e1ca659 100644 --- a/code/modules/admin/verbs/deadsay.dm +++ b/code/modules/admin/verbs/deadsay.dm @@ -44,4 +44,4 @@ else if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_DEAD)) // show the message to regular ghosts who have deadchat toggled on M.show_message(rendered, 2) - feedback_add_details("admin_verb","D") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! \ No newline at end of file + feedback_add_details("admin_verb","D") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index da3d9439..1bd128a8 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -73,11 +73,11 @@ client/proc/one_click_antag() candidates += applicant if(candidates.len) - var/numTratiors = min(candidates.len, 3) + var/numTraitors = min(candidates.len, 3) - for(var/i = 0, i [key_name_admin(M)] : [msg]", 1) feedback_add_details("admin_verb","SMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/client/proc/cmd_mentor_check_new_players() //Allows mentors / admins to determine who the newer players are. + set category = "Admin" + set name = "Check new Players" + if(!holder) + src << "Only staff members may use this command." + + var/age = alert(src, "Age check", "Show accounts yonger then _____ days","7", "30" , "All") + + if(age == "All") + age = 9999999 + else + age = text2num(age) + + var/missing_ages = 0 + var/msg = "" + for(var/client/C in clients) + if(C.player_age == "Requires database") + missing_ages = 1 + continue + if(C.player_age < age) + msg += "[key_name_admin(C)]: account is [C.player_age] days old
        " + + if(missing_ages) + src << "Some accounts did not have proper ages set in their clients. This function requires database to be present" + + if(msg != "") + src << browse(msg, "window=Player_age_check") + else + src << "No matches for that age range found." + + /client/proc/cmd_admin_world_narrate() // Allows administrators to fluff events a little easier -- TLE set category = "Special Verbs" set name = "Global Narrate" diff --git a/code/modules/admin/verbs/vox_raiders.dm b/code/modules/admin/verbs/vox_raiders.dm index d00435e1..941aa8f9 100644 --- a/code/modules/admin/verbs/vox_raiders.dm +++ b/code/modules/admin/verbs/vox_raiders.dm @@ -18,14 +18,9 @@ var/global/vox_tick = 1 equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. equip_to_slot_or_del(new /obj/item/device/chameleon(src), slot_l_store) - var/obj/item/weapon/crossbow/W = new(src) - W.cell = new /obj/item/weapon/cell/crap(W) - W.cell.charge = 500 + var/obj/item/weapon/spikethrower/W = new(src) equip_to_slot_or_del(W, slot_r_hand) - var/obj/item/stack/rods/A = new(src) - A.amount = 20 - equip_to_slot_or_del(A, slot_l_hand) if(2) // Vox engineer! equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/pressure(src), slot_wear_suit) diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index c85ee015..81f53ec4 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -18,6 +18,7 @@ var/area = null var/time_died_as_mouse = null //when the client last died as a mouse + var/adminhelped = 0 /////////////// //SOUND STUFF// @@ -32,6 +33,10 @@ // comment out the line below when debugging locally to enable the options & messages menu //control_freak = 1 + var/received_irc_pm = -99999 + var/irc_admin //IRC admin that spoke with them last. + var/mute_irc = 0 + //////////////////////////////////// //things that require the database// diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 1d955a9e..b3cdba60 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -45,6 +45,18 @@ cmd_admin_pm(C,null) return + if(href_list["irc_msg"]) + if(!holder && received_irc_pm < world.time - 6000) //Worse they can do is spam IRC for 10 minutes + usr << "You are no longer able to use this, it's been more then 10 minutes since an admin on IRC has responded to you" + return + if(mute_irc) + usr << "" + return + cmd_admin_irc_pm() + return + + + //Logs all hrefs if(config && config.log_hrefs && href_logfile) href_logfile << "[time2text(world.timeofday,"hh:mm")] [src] (usr:[usr]) || [hsrc ? "[hsrc] " : ""][href]
        " @@ -179,6 +191,7 @@ var/DBQuery/query = dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM erro_player WHERE ckey = '[sql_ckey]'") query.Execute() var/sql_id = 0 + player_age = 0 // New players won't have an entry so knowing we have a connection we set this to zero to be updated if their is a record. while(query.NextRow()) sql_id = query.item[1] player_age = text2num(query.item[2]) @@ -243,12 +256,11 @@ /client/proc/send_resources() // preload_vox() //Causes long delays with initial start window and subsequent windows when first logged in. - // Send NanoUI resources to this client - nanomanager.send_resources(src) - getFiles( 'html/search.js', 'html/panels.css', + 'html/painew.png', + 'html/loading.gif', 'icons/pda_icons/pda_atmos.png', 'icons/pda_icons/pda_back.png', 'icons/pda_icons/pda_bell.png', diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 05dbe22f..f85f251f 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -54,6 +54,7 @@ datum/preferences var/age = 30 //age of character var/b_type = "A+" //blood type (not-chooseable) var/underwear = 1 //underwear type + var/undershirt = 1 //undershirt type var/backbag = 2 //backpack type var/h_style = "Bald" //Hair type var/r_hair = 0 //Hair color @@ -63,7 +64,10 @@ datum/preferences var/r_facial = 0 //Face hair color var/g_facial = 0 //Face hair color var/b_facial = 0 //Face hair color - var/s_tone = 0 //Skin color + var/s_tone = 0 //Skin tone + var/r_skin = 0 //Skin color + var/g_skin = 0 //Skin color + var/b_skin = 0 //Skin color var/r_eyes = 0 //Eye color var/g_eyes = 0 //Eye color var/b_eyes = 0 //Eye color @@ -338,6 +342,8 @@ datum/preferences else dat += "Underwear: [underwear_f[underwear]]
        " + dat += "Undershirt: [undershirt_t[undershirt]]
        " + dat += "Backpack Type:
        [backbaglist[backbag]]
        " dat += "Nanotrasen Relation:
        [nanotrasen_relation]
        " @@ -374,7 +380,10 @@ datum/preferences dat += " Style: [f_style]
        " dat += "
        Eyes
        " - dat += "Change Color
        __
        " + dat += "Change Color
        __

        " + + dat += "
        Body Color
        " + dat += "Change Color
        __
        " dat += "

        " if(jobban_isbanned(user, "Syndicate")) @@ -401,9 +410,9 @@ datum/preferences dat += "Reset Setup" dat += "" - user << browse(dat, "window=preferences;size=560x580") + user << browse(dat, "window=preferences;size=560x736") - proc/SetChoices(mob/user, limit = 16, list/splitJobs = list("Chief Medical Officer"), width = 550, height = 550) + proc/SetChoices(mob/user, limit = 16, list/splitJobs = list("Chief Medical Officer"), width = 550, height = 660) if(!job_master) return @@ -415,7 +424,7 @@ datum/preferences var/HTML = "" HTML += "
        " - HTML += "Choose occupation chances
        Unavailable occupations are in red.

        " + HTML += "Choose occupation chances
        Unavailable occupations are crossed out.

        " HTML += "
        \[Done\]

        " // Easier to press up here. HTML += " - + + "} - - - -
        " // Table within a table for alignment, also allows you to easily add more colomns. HTML += "" @@ -440,11 +449,11 @@ datum/preferences var/rank = job.title lastJob = job if(jobban_isbanned(user, rank)) - HTML += "[rank]" + HTML += "[rank]" continue if(!job.player_old_enough(user.client)) var/available_in_days = job.available_in_days(user.client) - HTML += "[rank]" + HTML += "[rank]" continue if((job_civilian_low & ASSISTANT) && (rank != "Assistant")) HTML += "[rank]" @@ -552,6 +561,8 @@ datum/preferences return proc/SetAntagoptions(mob/user) + if(uplinklocation == "" || !uplinklocation) + uplinklocation = "PDA" var/HTML = "" HTML += "
        " HTML += "Antagonist Options
        " @@ -843,12 +854,19 @@ datum/preferences if("underwear") underwear = rand(1,underwear_m.len) ShowChoices(user) + if("undershirt") + undershirt = rand(1,undershirt_t.len) + ShowChoices(user) if("eyes") r_eyes = rand(0,255) g_eyes = rand(0,255) b_eyes = rand(0,255) if("s_tone") s_tone = random_skin_tone() + if("s_color") + r_skin = rand(0,255) + g_skin = rand(0,255) + b_skin = rand(0,255) if("bag") backbag = rand(1,4) /*if("skin_style") @@ -963,7 +981,7 @@ datum/preferences b_type = new_b_type if("hair") - if(species == "Human" || species == "Unathi") + if(species == "Human" || species == "Unathi" || species == "Tajaran" || species == "Skrell") var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference") as color|null if(new_hair) r_hair = hex2num(copytext(new_hair, 2, 4)) @@ -1019,6 +1037,15 @@ datum/preferences underwear = underwear_options.Find(new_underwear) ShowChoices(user) + if("undershirt") + var/list/undershirt_options + undershirt_options = undershirt_t + + var/new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in undershirt_options + if (new_undershirt) + undershirt = undershirt_options.Find(new_undershirt) + ShowChoices(user) + if("eyes") var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference") as color|null if(new_eyes) @@ -1033,6 +1060,14 @@ datum/preferences if(new_s_tone) s_tone = 35 - max(min( round(new_s_tone), 220),1) + if("skin") + if(species == "Unathi" || species == "Tajaran" || species == "Skrell") + var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference") as color|null + if(new_skin) + r_skin = hex2num(copytext(new_skin, 2, 4)) + g_skin = hex2num(copytext(new_skin, 4, 6)) + b_skin = hex2num(copytext(new_skin, 6, 8)) + if("ooccolor") var/new_ooccolor = input(user, "Choose your OOC colour:", "Game Preference") as color|null if(new_ooccolor) @@ -1263,6 +1298,10 @@ datum/preferences character.g_facial = g_facial character.b_facial = b_facial + character.r_skin = r_skin + character.g_skin = g_skin + character.b_skin = b_skin + character.s_tone = s_tone character.h_style = h_style @@ -1295,6 +1334,10 @@ datum/preferences underwear = 0 //I'm sure this is 100% unnecessary, but I'm paranoid... sue me. //HAH NOW NO MORE MAGIC CLONING UNDIES character.underwear = underwear + if(undershirt > undershirt_t.len || undershirt < 1) + undershirt = 0 + character.undershirt = undershirt + if(backbag > 4 || backbag < 1) backbag = 1 //Same as above character.backbag = backbag diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 89f8301b..b1519ea3 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -84,8 +84,6 @@ S["be_special"] << be_special S["default_slot"] << default_slot S["toggles"] << toggles - S["UI_style_color"] << UI_style_color - S["UI_style_alpha"] << UI_style_alpha return 1 @@ -119,12 +117,16 @@ S["facial_green"] >> g_facial S["facial_blue"] >> b_facial S["skin_tone"] >> s_tone + S["skin_red"] >> r_skin + S["skin_green"] >> g_skin + S["skin_blue"] >> b_skin S["hair_style_name"] >> h_style S["facial_style_name"] >> f_style S["eyes_red"] >> r_eyes S["eyes_green"] >> g_eyes S["eyes_blue"] >> b_eyes S["underwear"] >> underwear + S["undershirt"] >> undershirt S["backbag"] >> backbag S["b_type"] >> b_type @@ -158,6 +160,9 @@ S["uplinklocation"] >> uplinklocation + S["UI_style_color"] << UI_style_color + S["UI_style_alpha"] << UI_style_alpha + //Sanitize metadata = sanitize_text(metadata, initial(metadata)) real_name = reject_bad_name(real_name) @@ -175,12 +180,16 @@ g_facial = sanitize_integer(g_facial, 0, 255, initial(g_facial)) b_facial = sanitize_integer(b_facial, 0, 255, initial(b_facial)) s_tone = sanitize_integer(s_tone, -185, 34, initial(s_tone)) + r_skin = sanitize_integer(r_skin, 0, 255, initial(r_skin)) + g_skin = sanitize_integer(g_skin, 0, 255, initial(g_skin)) + b_skin = sanitize_integer(b_skin, 0, 255, initial(b_skin)) h_style = sanitize_inlist(h_style, hair_styles_list, initial(h_style)) f_style = sanitize_inlist(f_style, facial_hair_styles_list, initial(f_style)) r_eyes = sanitize_integer(r_eyes, 0, 255, initial(r_eyes)) g_eyes = sanitize_integer(g_eyes, 0, 255, initial(g_eyes)) b_eyes = sanitize_integer(b_eyes, 0, 255, initial(b_eyes)) underwear = sanitize_integer(underwear, 1, underwear_m.len, initial(underwear)) + undershirt = sanitize_integer(undershirt, 1, undershirt_t.len, initial(undershirt)) backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag)) b_type = sanitize_text(b_type, initial(b_type)) @@ -225,12 +234,16 @@ S["facial_green"] << g_facial S["facial_blue"] << b_facial S["skin_tone"] << s_tone + S["skin_red"] << r_skin + S["skin_green"] << g_skin + S["skin_blue"] << b_skin S["hair_style_name"] << h_style S["facial_style_name"] << f_style S["eyes_red"] << r_eyes S["eyes_green"] << g_eyes S["eyes_blue"] << b_eyes S["underwear"] << underwear + S["undershirt"] << undershirt S["backbag"] << backbag S["b_type"] << b_type @@ -264,6 +277,9 @@ S["uplinklocation"] << uplinklocation + S["UI_style_color"] << UI_style_color + S["UI_style_alpha"] << UI_style_alpha + return 1 diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 7b275641..d7dfe3b2 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -5,6 +5,10 @@ //BS12: Species-restricted clothing check. /obj/item/clothing/mob_can_equip(M as mob, slot) + //if we can equip the item anyway, don't bother with species_restricted (aslo cuts down on spam) + if (!..()) + return 0 + if(species_restricted && istype(M,/mob/living/carbon/human)) var/wearable = null @@ -26,7 +30,7 @@ M << "\red Your species cannot wear [src]." return 0 - return ..() + return 1 //Ears: headsets, earmuffs and tiny objects /obj/item/clothing/ears @@ -134,6 +138,7 @@ BLIND // can't see anything /obj/item/clothing/gloves/emp_act(severity) if(cell) + //why is this not part of the powercell code? cell.charge -= 1000 / severity if (cell.charge < 0) cell.charge = 0 @@ -151,6 +156,7 @@ BLIND // can't see anything icon = 'icons/obj/clothing/hats.dmi' body_parts_covered = HEAD slot_flags = SLOT_HEAD + w_class = 2.0 //Mask @@ -186,6 +192,7 @@ BLIND // can't see anything slot_flags = SLOT_OCLOTHING var/blood_overlay_type = "suit" siemens_coefficient = 0.9 + w_class = 3 //Spacesuit //Note: Everything in modules/clothing/spacesuits should have the entire suit grouped together. @@ -194,7 +201,7 @@ BLIND // can't see anything name = "Space helmet" icon_state = "space" desc = "A special helmet designed for work in a hazardous, low-pressure environment." - flags = FPRINT | TABLEPASS | HEADCOVERSEYES | BLOCKHAIR | HEADCOVERSMOUTH | STOPSPRESSUREDMAGE + flags = FPRINT | TABLEPASS | HEADCOVERSEYES | BLOCKHAIR | HEADCOVERSMOUTH | STOPSPRESSUREDMAGE | THICKMATERIAL item_state = "space" permeability_coefficient = 0.01 armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50) @@ -212,12 +219,12 @@ BLIND // can't see anything w_class = 4//bulky item gas_transfer_coefficient = 0.01 permeability_coefficient = 0.02 - flags = FPRINT | TABLEPASS | STOPSPRESSUREDMAGE + flags = FPRINT | TABLEPASS | STOPSPRESSUREDMAGE | THICKMATERIAL body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen) slowdown = 3 armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE siemens_coefficient = 0.9 @@ -232,6 +239,7 @@ BLIND // can't see anything flags = FPRINT | TABLEPASS slot_flags = SLOT_ICLOTHING armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + w_class = 3 var/has_sensor = 1//For the crew computer 2 = unable to change mode var/sensor_mode = 0 /* @@ -241,19 +249,18 @@ BLIND // can't see anything */ var/obj/item/clothing/tie/hastie = null var/displays_id = 1 + var/rolled_down = 0 + var/basecolor /obj/item/clothing/under/attackby(obj/item/I, mob/user) + if(hastie) + hastie.attackby(I, user) + return + if(!hastie && istype(I, /obj/item/clothing/tie)) user.drop_item() hastie = I - I.loc = src - user << "You attach [I] to [src]." - - if (istype(hastie,/obj/item/clothing/tie/holster)) - verbs += /obj/item/clothing/under/proc/holster - - if (istype(hastie,/obj/item/clothing/tie/storage)) - verbs += /obj/item/clothing/under/proc/storage + hastie.on_attached(src, user) if(istype(loc, /mob/living/carbon/human)) var/mob/living/carbon/human/H = loc @@ -263,6 +270,32 @@ BLIND // can't see anything ..() +/obj/item/clothing/under/attack_hand(mob/user as mob) + //only forward to the attached accessory if the clothing is equipped (not in a storage) + if(hastie && src.loc == user) + hastie.attack_hand(user) + return + ..() + +//This is to ensure people can take off suits when there is an attached accessory +/obj/item/clothing/under/MouseDrop(obj/over_object as obj) + if (ishuman(usr) || ismonkey(usr)) + //makes sure that the clothing is equipped so that we can't drag it into our hand from miles away. + if (!(src.loc == usr)) + return + + if (!( usr.restrained() ) && !( usr.stat )) + switch(over_object.name) + if("r_hand") + usr.u_equip(src) + usr.put_in_r_hand(src) + if("l_hand") + usr.u_equip(src) + usr.put_in_l_hand(src) + src.add_fingerprint(usr) + return + return + /obj/item/clothing/under/examine() set src in view() ..() @@ -278,13 +311,10 @@ BLIND // can't see anything if(hastie) usr << "\A [hastie] is clipped to it." -/obj/item/clothing/under/verb/toggle() - set name = "Toggle Suit Sensors" - set category = "Object" - set src in usr +/obj/item/clothing/under/proc/set_sensors(mob/usr as mob) var/mob/M = usr if (istype(M, /mob/dead/)) return - if (usr.stat) return + if (usr.stat || usr.restrained()) return if(has_sensor >= 2) usr << "The controls are locked." return 0 @@ -294,19 +324,69 @@ BLIND // can't see anything var/list/modes = list("Off", "Binary sensors", "Vitals tracker", "Tracking beacon") var/switchMode = input("Select a sensor mode:", "Suit Sensor Mode", modes[sensor_mode + 1]) in modes + if(get_dist(usr, src) > 1) + usr << "You have moved too far away." + return sensor_mode = modes.Find(switchMode) - 1 - switch(sensor_mode) - if(0) - usr << "You disable your suit's remote sensing equipment." - if(1) - usr << "Your suit will now report whether you are live or dead." - if(2) - usr << "Your suit will now report your vital lifesigns." - if(3) - usr << "Your suit will now report your vital lifesigns as well as your coordinate position." + if (src.loc == usr) + switch(sensor_mode) + if(0) + usr << "You disable your suit's remote sensing equipment." + if(1) + usr << "Your suit will now report whether you are live or dead." + if(2) + usr << "Your suit will now report your vital lifesigns." + if(3) + usr << "Your suit will now report your vital lifesigns as well as your coordinate position." + else if (istype(src.loc, /mob)) + switch(sensor_mode) + if(0) + for(var/mob/V in viewers(usr, 1)) + V.show_message("\red [usr] disables [src.loc]'s remote sensing equipment.", 1) + if(1) + for(var/mob/V in viewers(usr, 1)) + V.show_message("[usr] turns [src.loc]'s remote sensors to binary.", 1) + if(2) + for(var/mob/V in viewers(usr, 1)) + V.show_message("[usr] sets [src.loc]'s sensors to track vitals.", 1) + if(3) + for(var/mob/V in viewers(usr, 1)) + V.show_message("[usr] sets [src.loc]'s sensors to maximum.", 1) + +/obj/item/clothing/under/verb/toggle() + set name = "Toggle Suit Sensors" + set category = "Object" + set src in usr + set_sensors(usr) ..() +/obj/item/clothing/under/verb/rollsuit() + set name = "Roll Down Jumpsuit" + set category = "Object" + set src in usr + if(!istype(usr, /mob/living)) return + if(usr.stat) return + + if(copytext(item_color,-2) != "_d") + basecolor = item_color + if(basecolor + "_d_s" in icon_states('icons/mob/uniform.dmi')) + item_color = item_color == "[basecolor]" ? "[basecolor]_d" : "[basecolor]" + usr.update_inv_w_uniform() + else + usr << "You cannot roll down the uniform!" + +/obj/item/clothing/under/proc/remove_accessory(mob/user as mob) + if(!hastie) + return + + hastie.on_removed(user) + hastie = null + + if(istype(loc, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = loc + H.update_inv_w_uniform() + /obj/item/clothing/under/verb/removetie() set name = "Remove Accessory" set category = "Object" @@ -314,80 +394,10 @@ BLIND // can't see anything if(!istype(usr, /mob/living)) return if(usr.stat) return - if(hastie) - if (istype(hastie,/obj/item/clothing/tie/holster)) - verbs -= /obj/item/clothing/under/proc/holster - - if (istype(hastie,/obj/item/clothing/tie/storage)) - verbs -= /obj/item/clothing/under/proc/storage - var/obj/item/clothing/tie/storage/W = hastie - if (W.hold) - W.hold.close(usr) - - usr.put_in_hands(hastie) - hastie = null - - if(istype(loc, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = loc - H.update_inv_w_uniform() + src.remove_accessory(usr) /obj/item/clothing/under/rank/New() sensor_mode = pick(0,1,2,3) ..() -/obj/item/clothing/under/proc/holster() - set name = "Holster" - set category = "Object" - set src in usr - if(!istype(usr, /mob/living)) return - if(usr.stat) return - - if (!hastie || !istype(hastie,/obj/item/clothing/tie/holster)) - usr << "\red You need a holster for that!" - return - var/obj/item/clothing/tie/holster/H = hastie - - if(!H.holstered) - if(!istype(usr.get_active_hand(), /obj/item/weapon/gun)) - usr << "\blue You need your gun equiped to holster it." - return - var/obj/item/weapon/gun/W = usr.get_active_hand() - if (!W.isHandgun()) - usr << "\red This gun won't fit in \the [H]!" - return - H.holstered = usr.get_active_hand() - usr.drop_item() - H.holstered.loc = src - usr.visible_message("\blue \The [usr] holsters \the [H.holstered].", "You holster \the [H.holstered].") - else - if(istype(usr.get_active_hand(),/obj) && istype(usr.get_inactive_hand(),/obj)) - usr << "\red You need an empty hand to draw the gun!" - else - if(usr.a_intent == "hurt") - usr.visible_message("\red \The [usr] draws \the [H.holstered], ready to shoot!", \ - "\red You draw \the [H.holstered], ready to shoot!") - else - usr.visible_message("\blue \The [usr] draws \the [H.holstered], pointing it at the ground.", \ - "\blue You draw \the [H.holstered], pointing it at the ground.") - usr.put_in_hands(H.holstered) - H.holstered = null - -/obj/item/clothing/under/proc/storage() - set name = "Look in storage" - set category = "Object" - set src in usr - if(!istype(usr, /mob/living)) return - if(usr.stat) return - - if (!hastie || !istype(hastie,/obj/item/clothing/tie/storage)) - usr << "\red You need something to store items in for that!" - return - var/obj/item/clothing/tie/storage/W = hastie - - if (!istype(W.hold)) - return - - W.hold.loc = usr - W.hold.attack_hand(usr) - diff --git a/code/modules/clothing/gloves/stungloves.dm b/code/modules/clothing/gloves/stungloves.dm index 2c95cd65..f950aa3a 100644 --- a/code/modules/clothing/gloves/stungloves.dm +++ b/code/modules/clothing/gloves/stungloves.dm @@ -1,76 +1,82 @@ /obj/item/clothing/gloves/attackby(obj/item/weapon/W, mob/user) - if(istype(src, /obj/item/clothing/gloves/boxing)) //quick fix for stunglove overlay not working nicely with boxing gloves. + if(istype(src, /obj/item/clothing/gloves/boxing)) //quick fix for stunglove overlay not working nicely with boxing gloves. user << "That won't work." //i'm not putting my lips on that! ..() return + + //add wires if(istype(W, /obj/item/weapon/cable_coil)) - if(!("stunglove" in species_restricted)) - var/obj/item/weapon/cable_coil/C = W - if(!wired) - if(C.amount >= 2) - C.use(2) - wired = 1 - siemens_coefficient = 3.0 - user << "You wrap some wires around [src]." - update_icon() - else - user << "There is not enough wire to cover [src]." - else - user << "[src] are already wired." - else - user << "" - + var/obj/item/weapon/cable_coil/C = W + if (clipped) + user << "The [src] are too badly mangled for wiring." + return + + if(wired) + user << "The [src] are already wired." + return + + if(C.amount < 2) + user << "There is not enough wire to cover the [src]." + return + + C.use(2) + wired = 1 + siemens_coefficient = 3.0 + user << "You wrap some wires around the [src]." + update_icon() + return + + //add cell else if(istype(W, /obj/item/weapon/cell)) if(!wired) - user << "[src] need to be wired first." + user << "The [src] need to be wired first." else if(!cell) user.drop_item() W.loc = src cell = W - user << "You attach a cell to [src]." + user << "You attach the [cell] to the [src]." update_icon() else - user << "[src] already have a cell." + user << "A [cell] is already attached to the [src]." + return else if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel)) - - wired = null - + //stunglove stuff if(cell) cell.updateicon() + user << "You cut the [cell] away from the [src]." cell.loc = get_turf(src.loc) cell = null - if(clipped == 0) - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) - user.visible_message("\red [user] cut the fingertips off [src].","\red You cut the fingertips off [src].") - clipped = 1 - if("exclude" in species_restricted) - name = "mangled [name]" - desc = "[desc] They have had the fingertips cut off of them." - species_restricted -= "Unathi" - species_restricted -= "Tajaran" - species_restricted += "stunglove" - else if(clipped == 1) - user << "[src] have already been clipped!" - update_icon() - - return - - if(cell) - cell.updateicon() - cell.loc = get_turf(src.loc) - cell = null - user << "You cut the cell away from [src]." update_icon() return if(wired) //wires disappear into the void because fuck that shit wired = 0 siemens_coefficient = initial(siemens_coefficient) - user << "You cut the wires away from [src]." + user << "You cut the wires away from the [src]." update_icon() - ..() - return + return + + //clipping fingertips + if(!clipped) + playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) + user.visible_message("\red [user] cuts the fingertips off of the [src].","\red You cut the fingertips off of the [src].") + + clipped = 1 + name = "mangled [name]" + desc = "[desc]
        They have had the fingertips cut off of them." + if("exclude" in species_restricted) + species_restricted -= "Unathi" + species_restricted -= "Tajaran" + return + else + user << "The [src] have already been clipped!" + update_icon() + return + + return + + ..() /obj/item/clothing/gloves/update_icon() ..() diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 26ac1213..a28da73f 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -2,7 +2,7 @@ name = "helmet" desc = "Standard Security gear. Protects the head from impacts." icon_state = "helmet" - flags = FPRINT | TABLEPASS | HEADCOVERSEYES + flags = FPRINT | TABLEPASS | HEADCOVERSEYES | THICKMATERIAL item_state = "helmet" armor = list(melee = 50, bullet = 15, laser = 50,energy = 10, bomb = 25, bio = 0, rad = 0) flags_inv = HIDEEARS|HIDEEYES @@ -11,6 +11,7 @@ heat_protection = HEAD max_heat_protection_temperature = HELMET_MAX_HEAT_PROTECTION_TEMPERATURE siemens_coefficient = 0.7 + w_class = 3 /obj/item/clothing/head/helmet/warden name = "warden's hat" diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 65f3df9b..e703e7a4 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -24,6 +24,7 @@ flags_inv = (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) icon_action_button = "action_welding" siemens_coefficient = 0.9 + w_class = 3 /obj/item/clothing/head/welding/attack_self() toggle() @@ -125,6 +126,7 @@ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE var/brightness_on = 2 //luminosity when on var/on = 0 + w_class = 3 attack_self(mob/user) if(!isturf(user.loc)) diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm index 2f6edd7f..b549a09d 100644 --- a/code/modules/clothing/masks/breath.dm +++ b/code/modules/clothing/masks/breath.dm @@ -43,18 +43,11 @@ icon_state = "voxmask" item_state = "voxmask" permeability_coefficient = 0.01 + species_restricted = ("Vox") toggle() set category = "Object" set name = "Adjust mask" set src in usr - usr << "You can't really adjust this mask - it's moulded to your beak!" - -/obj/item/clothing/mask/breath/vox/mob_can_equip(M as mob, slot) - var/mob/living/carbon/human/V = M - if(V.species.name != "Vox") - V << "This clearly isn't designed for your species!" - return 0 - - return ..() + usr << "You can't really adjust this mask - it's moulded to your beak!" \ No newline at end of file diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 0dda528a..13177588 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -121,12 +121,14 @@ icon_state = "slippers" item_state = "slippers" species_restricted = null + w_class = 2 /obj/item/clothing/shoes/slippers_worn name = "worn bunny slippers" desc = "Fluffy..." icon_state = "slippers_worn" item_state = "slippers_worn" + w_class = 2 /obj/item/clothing/shoes/laceup name = "laceup shoes" diff --git a/code/modules/clothing/spacesuits/alien.dm b/code/modules/clothing/spacesuits/alien.dm index f038aa44..4e931595 100644 --- a/code/modules/clothing/spacesuits/alien.dm +++ b/code/modules/clothing/spacesuits/alien.dm @@ -130,12 +130,14 @@ icon_state = "vox-carapace" item_state = "vox-carapace" desc = "A glowing visor, perhaps stolen from a depressed Cylon." + species_restricted = list("Vox","Vox Armalis") /obj/item/clothing/suit/space/vox/carapace name = "alien carapace armour" icon_state = "vox-carapace" item_state = "vox-carapace" desc = "An armoured, segmented carapace with glowing purple lights. It looks pretty run-down." + species_restricted = list("Vox","Vox Armalis") /obj/item/clothing/head/helmet/space/vox/stealth name = "alien stealth helmet" @@ -187,7 +189,7 @@ siemens_coefficient = 0 permeability_coefficient = 0.05 item_color="gloves-vox" - species_restricted = list("Vox") + species_restricted = list("Vox","Vox Armalis") /obj/item/clothing/shoes/magboots/vox @@ -195,7 +197,7 @@ name = "vox magclaws" item_state = "boots-vox" icon_state = "boots-vox" - species_restricted = list("Vox") + species_restricted = list("Vox","Vox Armalis") action_button_name = "Toggle the magclaws" /obj/item/clothing/shoes/magboots/vox/attack_self(mob/user) @@ -206,10 +208,14 @@ user << "You relax your deathgrip on the flooring." else //make sure these can only be used when equipped. - if (!is_equipped()) + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + if (H.shoes != src) user << "You will have to put on the [src] before you can do that." return - + + flags |= NOSLIP magpulse = 1 canremove = 0 //kinda hard to take off magclaws when you are gripping them tightly. diff --git a/code/modules/clothing/spacesuits/captain.dm b/code/modules/clothing/spacesuits/captain.dm index 12604e73..281b3086 100644 --- a/code/modules/clothing/spacesuits/captain.dm +++ b/code/modules/clothing/spacesuits/captain.dm @@ -23,7 +23,7 @@ allowed = list(/obj/item/weapon/tank/emergency_oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy, /obj/item/weapon/gun/projectile, /obj/item/ammo_magazine, /obj/item/ammo_casing, /obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs) slowdown = 1.5 armor = list(melee = 65, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE siemens_coefficient = 0.7 diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index 05a72c7e..c729c4a4 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -22,7 +22,7 @@ allowed = list(/obj/item/weapon/tank/emergency_oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy, /obj/item/weapon/gun/projectile, /obj/item/ammo_magazine, /obj/item/ammo_casing, /obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs) slowdown = 1.5 armor = list(melee = 65, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE siemens_coefficient = 0.7 diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm index 798fc4a3..ef73f239 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -75,13 +75,14 @@ icon_state = "rig0-mining" item_state = "mining_helm" item_color = "mining" + armor = list(melee = 50, bullet = 5, laser = 20,energy = 5, bomb = 55, bio = 100, rad = 20) /obj/item/clothing/suit/space/rig/mining icon_state = "rig-mining" name = "mining hardsuit" desc = "A special suit that protects against hazardous, low pressure environments. Has reinforced plating." item_state = "mining_hardsuit" - + armor = list(melee = 50, bullet = 5, laser = 20,energy = 5, bomb = 55, bio = 100, rad = 20) //Syndicate rig @@ -94,7 +95,7 @@ armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 35, bio = 100, rad = 60) siemens_coefficient = 0.6 var/obj/machinery/camera/camera - species_restricted = list("exclude","Vox") + species_restricted = list("exclude","Unathi","Tajaran","Skrell","Vox") /obj/item/clothing/head/helmet/space/rig/syndi/attack_self(mob/user) if(camera) ..(user) @@ -120,7 +121,7 @@ armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 60) allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs) siemens_coefficient = 0.6 - species_restricted = list("exclude","Vox") + species_restricted = list("exclude","Unathi","Tajaran","Skrell","Vox") //Wizard Rig @@ -153,6 +154,7 @@ icon_state = "rig0-medical" item_state = "medical_helm" item_color = "medical" + armor = list(melee = 30, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 50) /obj/item/clothing/suit/space/rig/medical icon_state = "rig-medical" @@ -160,7 +162,7 @@ desc = "A special suit that protects against hazardous, low pressure environments. Has minor radiation shielding." item_state = "medical_hardsuit" allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/storage/firstaid,/obj/item/device/healthanalyzer,/obj/item/stack/medical) - + armor = list(melee = 30, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 50) //Security /obj/item/clothing/head/helmet/space/rig/security @@ -184,18 +186,18 @@ //Atmospherics Rig (BS12) /obj/item/clothing/head/helmet/space/rig/atmos - desc = "A special helmet designed for work in a hazardous, low pressure environments. Has reduced radiation shielding and protective plating to allow for greater mobility." + desc = "A special helmet designed for work in a hazardous, low pressure environments. Has improved thermal protection and minor radiation shielding." name = "atmospherics hardsuit helmet" icon_state = "rig0-atmos" item_state = "atmos_helm" item_color = "atmos" - armor = list(melee = 40, bullet = 0, laser = 0, energy = 0, bomb = 25, bio = 100, rad = 0) + armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 50) max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE /obj/item/clothing/suit/space/rig/atmos - desc = "A special suit that protects against hazardous, low pressure environments. Has reduced radiation shielding to allow for greater mobility." + desc = "A special suit that protects against hazardous, low pressure environments. Has improved thermal protection and minor radiation shielding." icon_state = "rig-atmos" name = "atmos hardsuit" item_state = "atmos_hardsuit" - armor = list(melee = 40, bullet = 0, laser = 0, energy = 0, bomb = 25, bio = 100, rad = 0) + armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 35, bio = 100, rad = 50) max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index b132c38b..d0d91efb 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -2,7 +2,7 @@ /obj/item/clothing/suit/armor allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs) body_parts_covered = UPPER_TORSO|LOWER_TORSO - flags = FPRINT | TABLEPASS + flags = FPRINT | TABLEPASS | THICKMATERIAL cold_protection = UPPER_TORSO|LOWER_TORSO min_cold_protection_temperature = ARMOR_MIN_COLD_PROTECTION_TEMPERATURE diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index d7e7ba36..6e4b2545 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -22,7 +22,7 @@ slowdown = 1.0 allowed = list(/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/pen,/obj/item/device/flashlight/pen) armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL siemens_coefficient = 0.9 diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index de2c0f0f..54f18836 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -107,7 +107,8 @@ item_state = "hazard" blood_overlay_type = "armor" allowed = list (/obj/item/device/analyzer, /obj/item/device/flashlight, /obj/item/device/multitool, /obj/item/device/pipe_painter, /obj/item/device/radio, /obj/item/device/t_scanner, \ - /obj/item/weapon/crowbar, /obj/item/weapon/screwdriver, /obj/item/weapon/weldingtool, /obj/item/weapon/wirecutters, /obj/item/weapon/wrench, /obj/item/weapon/tank/emergency_oxygen) + /obj/item/weapon/crowbar, /obj/item/weapon/screwdriver, /obj/item/weapon/weldingtool, /obj/item/weapon/wirecutters, /obj/item/weapon/wrench, /obj/item/weapon/tank/emergency_oxygen, \ + /obj/item/clothing/mask/gas, /obj/item/taperoll/engineering) //Lawyer /obj/item/clothing/suit/storage/lawyer/bluejacket diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm index 238ad131..b8276868 100644 --- a/code/modules/clothing/suits/labcoat.dm +++ b/code/modules/clothing/suits/labcoat.dm @@ -100,6 +100,36 @@ return usr.update_inv_wear_suit() //so our overlays update +/obj/item/clothing/suit/storage/labcoat/red + name = "red labcoat" + desc = "A suit that protects against minor chemical spills. This one is red." + icon_state = "red_labcoat_open" + item_state = "red_labcoat" + +/obj/item/clothing/suit/storage/labcoat/blue + name = "blue labcoat" + desc = "A suit that protects against minor chemical spills. This one is blue." + icon_state = "blue_labcoat_open" + item_state = "blue_labcoat" + +/obj/item/clothing/suit/storage/labcoat/purple + name = "purple labcoat" + desc = "A suit that protects against minor chemical spills. This one is purple." + icon_state = "purple_labcoat_open" + item_state = "purple_labcoat" + +/obj/item/clothing/suit/storage/labcoat/orange + name = "orange labcoat" + desc = "A suit that protects against minor chemical spills. This one is orange." + icon_state = "orange_labcoat_open" + item_state = "orange_labcoat" + +/obj/item/clothing/suit/storage/labcoat/green + name = "green labcoat" + desc = "A suit that protects against minor chemical spills. This one is green." + icon_state = "green_labcoat_open" + item_state = "green_labcoat" + /obj/item/clothing/suit/storage/labcoat/cmo name = "chief medical officer's labcoat" desc = "Bluer than the standard model." @@ -113,22 +143,22 @@ item_state = "labgreen_open" /obj/item/clothing/suit/storage/labcoat/genetics - name = "Geneticist Labcoat" + name = "Geneticist labcoat" desc = "A suit that protects against minor chemical spills. Has a blue stripe on the shoulder." icon_state = "labcoat_gen_open" /obj/item/clothing/suit/storage/labcoat/chemist - name = "Chemist Labcoat" + name = "Chemist labcoat" desc = "A suit that protects against minor chemical spills. Has an orange stripe on the shoulder." icon_state = "labcoat_chem_open" /obj/item/clothing/suit/storage/labcoat/virologist - name = "Virologist Labcoat" + name = "Virologist labcoat" desc = "A suit that protects against minor chemical spills. Offers slightly more protection against biohazards than the standard model. Has a green stripe on the shoulder." icon_state = "labcoat_vir_open" armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 0) /obj/item/clothing/suit/storage/labcoat/science - name = "Scientist Labcoat" + name = "Scientist labcoat" desc = "A suit that protects against minor chemical spills. Has a purple stripe on the shoulder." icon_state = "labcoat_tox_open" diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index fb306960..7f95fb29 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -187,7 +187,7 @@ icon_state = "straight_jacket" item_state = "straight_jacket" body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL /obj/item/clothing/suit/ianshirt name = "worn shirt" diff --git a/code/modules/clothing/suits/storage.dm b/code/modules/clothing/suits/storage.dm new file mode 100644 index 00000000..cb03feb5 --- /dev/null +++ b/code/modules/clothing/suits/storage.dm @@ -0,0 +1,29 @@ +/obj/item/clothing/suit/storage + var/obj/item/weapon/storage/internal/pockets + +/obj/item/clothing/suit/storage/New() + ..() + pockets = new/obj/item/weapon/storage/internal(src) + pockets.storage_slots = 2 //two slots + pockets.max_w_class = 2 //fit only pocket sized items + pockets.max_combined_w_class = 4 + +/obj/item/clothing/suit/storage/attack_hand(mob/user as mob) + if (pockets.handle_attack_hand(user)) + ..(user) + +/obj/item/clothing/suit/storage/MouseDrop(obj/over_object as obj) + if (pockets.handle_mousedrop(usr, over_object)) + ..(over_object) + +/obj/item/clothing/suit/storage/attackby(obj/item/W as obj, mob/user as mob) + ..() + pockets.attackby(W, user) + +/obj/item/clothing/suit/storage/emp_act(severity) + pockets.emp_act(severity) + ..() + +/obj/item/clothing/suit/storage/hear_talk(mob/M, var/msg) + pockets.hear_talk(M, msg) + ..() \ No newline at end of file diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index 9b2d4c0f..a821682c 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -20,7 +20,7 @@ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/extinguisher) slowdown = 1.0 - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL flags = FPRINT | TABLEPASS | STOPSPRESSUREDMAGE heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE @@ -65,7 +65,7 @@ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS slowdown = 2 armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 100, bio = 0, rad = 0) - flags_inv = HIDEJUMPSUIT + flags_inv = HIDEJUMPSUIT|HIDETAIL heat_protection = UPPER_TORSO|LOWER_TORSO max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE siemens_coefficient = 0 @@ -101,7 +101,7 @@ gas_transfer_coefficient = 0.90 permeability_coefficient = 0.50 body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen) + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/clothing/head/radiation,/obj/item/clothing/mask/gas) slowdown = 1.5 armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100) - flags_inv = HIDEJUMPSUIT + flags_inv = HIDEJUMPSUIT|HIDETAIL diff --git a/code/modules/clothing/under/chameleon.dm b/code/modules/clothing/under/chameleon.dm index ef7c4854..9fd06429 100644 --- a/code/modules/clothing/under/chameleon.dm +++ b/code/modules/clothing/under/chameleon.dm @@ -1,3 +1,7 @@ +//***************** +//**Cham Jumpsuit** +//***************** + /obj/item/clothing/under/chameleon //starts off as black name = "black jumpsuit" @@ -6,60 +10,35 @@ item_color = "black" desc = "It's a plain jumpsuit. It seems to have a small dial on the wrist." origin_tech = "syndicate=3" - siemens_coefficient = 0.8 var/list/clothing_choices = list() New() ..() - for(var/U in typesof(/obj/item/clothing/under/color)-(/obj/item/clothing/under/color)) + var/blocked = list(/obj/item/clothing/under/chameleon, /obj/item/clothing/under/cloud, + /obj/item/clothing/under/golem, /obj/item/clothing/under/gimmick)//Prevent infinite loops and bad jumpsuits. + for(var/U in typesof(/obj/item/clothing/under)-blocked) var/obj/item/clothing/under/V = new U - src.clothing_choices += V - - for(var/U in typesof(/obj/item/clothing/under/rank)-(/obj/item/clothing/under/rank)) - var/obj/item/clothing/under/V = new U - src.clothing_choices += V + src.clothing_choices[V.name] = U return - - attackby(obj/item/clothing/under/U as obj, mob/user as mob) - ..() - if(istype(U, /obj/item/clothing/under/chameleon)) - user << "\red Nothing happens." - return - if(istype(U, /obj/item/clothing/under)) - if(src.clothing_choices.Find(U)) - user << "\red Pattern is already recognised by the suit." - return - src.clothing_choices += U - user << "\red Pattern absorbed by the suit." - - emp_act(severity) name = "psychedelic" desc = "Groovy!" icon_state = "psyche" item_color = "psyche" - spawn(200) - name = "Black Jumpsuit" - icon_state = "bl_suit" - item_color = "black" - desc = null - ..() - + update_icon() + usr.update_inv_w_uniform() verb/change() - set name = "Change Color" + set name = "Change Jumpsuit Appearance" set category = "Object" set src in usr - if(icon_state == "psyche") - usr << "\red Your suit is malfunctioning" - return - - var/obj/item/clothing/under/A - A = input("Select Colour to change it to", "BOOYEA", A) in clothing_choices - if(!A) + var/picked = input("Select jumpsuit to change it to", "Chameleon Jumpsuit")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype desc = null permeability_coefficient = 0.90 @@ -69,14 +48,415 @@ icon_state = A.icon_state item_state = A.item_state item_color = A.item_color - usr.update_inv_w_uniform() //so our overlays update. + if(usr) + usr.update_inv_w_uniform() //so our overlays update. +//***************** +//**Chameleon Hat** +//***************** +/obj/item/clothing/head/chameleon + name = "grey cap" + icon_state = "greysoft" + item_state = "greysoft" + item_color = "grey" + desc = "It looks like a plain hat, but upon closer inspection, there's an advanced holographic array installed inside. It seems to have a small dial inside." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() -/obj/item/clothing/under/chameleon/all/New() - ..() - var/blocked = list(/obj/item/clothing/under/chameleon, /obj/item/clothing/under/chameleon/all) - //to prevent an infinite loop - for(var/U in typesof(/obj/item/clothing/under)-blocked) - var/obj/item/clothing/under/V = new U - src.clothing_choices += V + New() + ..() + var/blocked = list(/obj/item/clothing/head/chameleon, + /obj/item/clothing/head/space/golem, /obj/item/clothing/head/justice,)//Prevent infinite loops and bad hats. + for(var/U in typesof(/obj/item/clothing/head)-blocked) + var/obj/item/clothing/head/V = new U + src.clothing_choices[V.name] = U + return + + emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "grey cap" + desc = "It's a baseball hat in a tasteful grey colour." + icon_state = "greysoft" + item_color = "grey" + update_icon() + usr.update_inv_head() + + verb/change() + set name = "Change Hat/Helmet Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select headwear to change it to", "Chameleon Hat")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + item_color = A.item_color + flags_inv = A.flags_inv + if(usr) + usr.update_inv_head() //so our overlays update. + +//****************** +//**Chameleon Suit** +//****************** + +/obj/item/clothing/suit/chameleon + name = "armor" + icon_state = "armor" + item_state = "armor" + desc = "It appears to be a vest of standard armor, except this is embedded with a hidden holographic cloaker, allowing it to change it's appearance, but offering no protection.. It seems to have a small dial inside." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + + New() + ..() + var/blocked = list(/obj/item/clothing/suit/chameleon, /obj/item/clothing/suit/space/space_ninja, + /obj/item/clothing/suit/golem, /obj/item/clothing/suit/suit, /obj/item/clothing/suit/cyborg_suit, /obj/item/clothing/suit/justice, + /obj/item/clothing/suit/greatcoat)//Prevent infinite loops and bad suits. + for(var/U in typesof(/obj/item/clothing/suit)-blocked) + var/obj/item/clothing/suit/V = new U + src.clothing_choices[V.name] = U + return + + emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "armor" + desc = "An armored vest that protects against some damage." + icon_state = "armor" + item_color = "armor" + update_icon() + usr.update_inv_wear_suit() + + verb/change() + set name = "Change Exosuit Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select exosuit to change it to", "Chameleon Exosuit")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + item_color = A.item_color + flags_inv = A.flags_inv + if(usr) + usr.update_inv_wear_suit() //so our overlays update. + +//******************* +//**Chameleon Shoes** +//******************* +/obj/item/clothing/shoes/chameleon + name = "black shoes" + icon_state = "black" + item_state = "black" + item_color = "black" + desc = "They're comfy black shoes, with clever cloaking technology built in. It seems to have a small dial on the back of each shoe." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + + New() + ..() + var/blocked = list(/obj/item/clothing/shoes/chameleon, + /obj/item/clothing/shoes/golem, /obj/item/clothing/shoes/syndigaloshes, /obj/item/clothing/shoes/cyborg)//prevent infinite loops and bad shoes. + for(var/U in typesof(/obj/item/clothing/shoes)-blocked) + var/obj/item/clothing/shoes/V = new U + src.clothing_choices[V.name] = U + return + + emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "black shoes" + desc = "A pair of black shoes." + icon_state = "black" + item_state = "black" + item_color = "black" + update_icon() + usr.update_inv_shoes() + + verb/change() + set name = "Change Footwear Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select shoes to change it to", "Chameleon Shoes")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + item_color = A.item_color + if(usr) + usr.update_inv_shoes() //so our overlays update. + +//********************** +//**Chameleon Backpack** +//********************** +/obj/item/weapon/storage/backpack/chameleon + name = "backpack" + icon_state = "backpack" + item_state = "backpack" + desc = "A backpack outfitted with cloaking tech. It seems to have a small dial inside, kept away from the storage." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + + New() + ..() + var/blocked = list(/obj/item/weapon/storage/backpack/chameleon, /obj/item/weapon/storage/backpack/satchel/withwallet) + for(var/U in typesof(/obj/item/weapon/storage/backpack)-blocked)//Prevent infinite loops and bad backpacks. + var/obj/item/weapon/storage/backpack/V = new U + src.clothing_choices[V.name] = U + return + + emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "backpack" + desc = "You wear this on your back and put items into it." + icon_state = "backpack" + item_state = "backpack" + update_icon() + usr.update_inv_back() + + verb/change() + set name = "Change Backpack Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select backpack to change it to", "Chameleon Backpack")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/weapon/storage/backpack/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + item_color = A.item_color + if(usr) + usr.update_inv_back() //so our overlays update. + +//******************** +//**Chameleon Gloves** +//******************** + +/obj/item/clothing/gloves/chameleon + name = "black gloves" + icon_state = "black" + item_state = "bgloves" + item_color = "brown" + desc = "It looks like a pair of gloves, but it seems to have a small dial inside." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + + New() + ..() + var/blocked = list(/obj/item/clothing/gloves/chameleon)//Prevent infinite loops and bad hats. + for(var/U in typesof(/obj/item/clothing/gloves)-blocked) + var/obj/item/clothing/gloves/V = new U + src.clothing_choices[V.name] = U + return + + emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "black gloves" + desc = "It looks like a pair of gloves, but it seems to have a small dial inside." + icon_state = "black" + item_color = "brown" + update_icon() + usr.update_inv_gloves() + + verb/change() + set name = "Change Gloves Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select gloves to change it to", "Chameleon Gloves")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + item_color = A.item_color + flags_inv = A.flags_inv + if(usr) + usr.update_inv_gloves() //so our overlays update. + +//****************** +//**Chameleon Mask** +//****************** + +/obj/item/clothing/mask/chameleon + name = "gas mask" + icon_state = "gas_alt" + item_state = "gas_alt" + desc = "It looks like a plain gask mask, but on closer inspection, it seems to have a small dial inside." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + + New() + ..() + var/blocked = list(/obj/item/clothing/mask/chameleon)//Prevent infinite loops and bad hats. + for(var/U in typesof(/obj/item/clothing/mask)-blocked) + var/obj/item/clothing/mask/V = new U + if(V) + src.clothing_choices[V.name] = U + return + + emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "gas mask" + desc = "It's a gas mask." + icon_state = "gas_alt" + update_icon() + usr.update_inv_wear_mask() + verb/change() + set name = "Change Mask Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select mask to change it to", "Chameleon Mask")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + flags_inv = A.flags_inv + if(usr) + usr.update_inv_wear_mask() //so our overlays update. + +//********************* +//**Chameleon Glasses** +//********************* + +/obj/item/clothing/glasses/chameleon + name = "Optical Meson Scanner" + icon_state = "meson" + item_state = "glasses" + desc = "It looks like a plain set of mesons, but on closer inspection, it seems to have a small dial inside." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + + New() + ..() + var/blocked = list(/obj/item/clothing/glasses/chameleon)//Prevent infinite loops and bad hats. + for(var/U in typesof(/obj/item/clothing/glasses)-blocked) + var/obj/item/clothing/glasses/V = new U + src.clothing_choices[V.name] = U + return + + emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "Optical Meson Scanner" + desc = "It's a set of mesons." + icon_state = "meson" + update_icon() + usr.update_inv_glasses() + + verb/change() + set name = "Change Glasses Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select glasses to change it to", "Chameleon Glasses")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + flags_inv = A.flags_inv + if(usr) + usr.update_inv_glasses() //so our overlays update. + +//***************** +//**Chameleon Gun** +//***************** +/obj/item/weapon/gun/projectile/chameleon + name = "desert eagle" + desc = "A fake Desert Eagle with a dial on the side to change the gun's disguise." + icon_state = "deagle" + w_class = 3.0 + max_shells = 7 + caliber = ".45" + origin_tech = "combat=2;materials=2;syndicate=8" + ammo_type = "/obj/item/ammo_casing/chameleon" + var/list/gun_choices = list() + + New() + ..() + var/blocked = list(/obj/item/weapon/gun/projectile/chameleon) + for(var/U in typesof(/obj/item/weapon/gun/)-blocked) + var/obj/item/weapon/gun/V = new U + src.gun_choices[V.name] = U + return + + emp_act(severity) + name = "desert eagle" + desc = "It's a desert eagle." + icon_state = "deagle" + update_icon() + usr.update_inv_r_hand() + usr.update_inv_l_hand() + + verb/change() + set name = "Change Gun Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select gun to change it to", "Chameleon Gun")as null|anything in gun_choices + if(!picked || !gun_choices[picked]) + return + var/newtype = gun_choices[picked] + var/obj/item/weapon/gun/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + flags_inv = A.flags_inv + if(usr) + usr.update_inv_r_hand() + usr.update_inv_l_hand() //so our overlays update. \ No newline at end of file diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm index e458475a..dad2f7c2 100644 --- a/code/modules/clothing/under/jobs/engineering.dm +++ b/code/modules/clothing/under/jobs/engineering.dm @@ -34,7 +34,7 @@ //Down below follows a partial attempt at getting the rolldown verb for jumpsuits. //Issue: Sprites vanishing again... Hueh - Skull132 - +/* /obj/item/clothing/under/rank/verb/rolldown() set name = "Roll Down Jumpsuit" set category = "Object" @@ -67,4 +67,5 @@ else usr << "You attempt to roll down your [src], before promptly realising how stupid it would be for you to expose your chest." return - usr.update_inv_w_uniform() \ No newline at end of file + usr.update_inv_w_uniform() */ + diff --git a/code/modules/clothing/under/jobs/medsci.dm b/code/modules/clothing/under/jobs/medsci.dm index 3ed419be..7aa6a055 100644 --- a/code/modules/clothing/under/jobs/medsci.dm +++ b/code/modules/clothing/under/jobs/medsci.dm @@ -31,9 +31,9 @@ /obj/item/clothing/under/rank/scientist desc = "It's made of a special fiber that provides minor protection against biohazards. It has markings that denote the wearer as a scientist." name = "scientist's jumpsuit" - icon_state = "toxins" + icon_state = "science" item_state = "w_suit" - item_color = "toxinswhite" + item_color = "sciencewhite" permeability_coefficient = 0.50 armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0) flags = FPRINT | TABLEPASS diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 1634216d..77ac281e 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -330,8 +330,8 @@ item_color = "plaid_purple" /obj/item/clothing/under/dress/plaid_green - name = "blue purple skirt" - desc = "A preppy greed skirt with a white blouse." + name = "green skirt" + desc = "A preppy green skirt with a white blouse." icon_state = "plaid_green" item_color = "plaid_green" diff --git a/code/modules/clothing/under/ties.dm b/code/modules/clothing/under/ties.dm index febc54c8..b7f9396c 100644 --- a/code/modules/clothing/under/ties.dm +++ b/code/modules/clothing/under/ties.dm @@ -8,6 +8,42 @@ flags = FPRINT | TABLEPASS slot_flags = 0 w_class = 2.0 + var/obj/item/clothing/under/has_suit = null //the suit the tie may be attached to + var/image/inv_overlay = null //overlay used when attached to clothing. + +/obj/item/clothing/tie/New() + ..() + inv_overlay = image("icon" = 'icons/obj/clothing/ties_overlay.dmi', "icon_state" = "[item_color? "[item_color]" : "[icon_state]"]") + +//when user attached an accessory to S +/obj/item/clothing/tie/proc/on_attached(obj/item/clothing/under/S, mob/user as mob) + if(!istype(S)) + return + has_suit = S + loc = has_suit + has_suit.overlays += inv_overlay + + user << "You attach [src] to [has_suit]." + src.add_fingerprint(user) + +/obj/item/clothing/tie/proc/on_removed(mob/user as mob) + if(!has_suit) + return + has_suit.overlays -= inv_overlay + has_suit = null + usr.put_in_hands(src) + src.add_fingerprint(user) + +//default attackby behaviour +/obj/item/clothing/tie/attackby(obj/item/I, mob/user) + ..() + +//default attack_hand behaviour +/obj/item/clothing/tie/attack_hand(mob/user as mob) + if(has_suit) + has_suit.remove_accessory(user) + return //we aren't an object on the ground so don't call parent + ..() /obj/item/clothing/tie/blue name = "blue tie" @@ -116,7 +152,7 @@ //Armbands /obj/item/clothing/tie/armband name = "red armband" - desc = "An fancy red armband!" + desc = "A fancy red armband!" icon_state = "red" item_color = "red" @@ -156,6 +192,7 @@ icon_state = "medgreen" item_color = "medgreen" +//holsters /obj/item/clothing/tie/holster name = "shoulder holster" desc = "A handgun holster." @@ -163,6 +200,105 @@ item_color = "holster" var/obj/item/weapon/gun/holstered = null +//subtypes can override this to specify what can be holstered +/obj/item/clothing/tie/holster/proc/can_holster(obj/item/weapon/gun/W) + return W.isHandgun() + +/obj/item/clothing/tie/holster/proc/holster(obj/item/I, mob/user as mob) + if(holstered) + user << "\red There is already a [holstered] holstered here!" + + if (!istype(I, /obj/item/weapon/gun)) + user << "\red Only guns can be holstered!" + + var/obj/item/weapon/gun/W = I + if (!can_holster(W)) + user << "\red This [W] won't fit in the [src]!" + return + + holstered = W + user.drop_from_inventory(holstered) + holstered.loc = src + holstered.add_fingerprint(user) + user.visible_message("\blue [user] holsters the [holstered].", "You holster the [holstered].") + +/obj/item/clothing/tie/holster/proc/unholster(mob/user as mob) + if(!holstered) + return + + if(istype(user.get_active_hand(),/obj) && istype(user.get_inactive_hand(),/obj)) + user << "\red You need an empty hand to draw the [holstered]!" + else + if(user.a_intent == "hurt") + usr.visible_message("\red [user] draws the [holstered], ready to shoot!", \ + "\red You draw the [holstered], ready to shoot!") + else + user.visible_message("\blue [user] draws the [holstered], pointing it at the ground.", \ + "\blue You draw the [holstered], pointing it at the ground.") + user.put_in_hands(holstered) + holstered.add_fingerprint(user) + holstered = null + +/obj/item/clothing/tie/holster/attack_hand(mob/user as mob) + if (has_suit) //if we are part of a suit + if (holstered) + unholster(user) + return + + ..(user) + +/obj/item/clothing/tie/holster/attackby(obj/item/W as obj, mob/user as mob) + holster(W, user) + +/obj/item/clothing/tie/holster/emp_act(severity) + if (holstered) + holstered.emp_act(severity) + ..() + +/obj/item/clothing/tie/holster/examine() + set src in view() + ..() + if (holstered) + usr << "A [holstered] is holstered here." + else + usr << "It is empty." + +/obj/item/clothing/tie/holster/on_attached(obj/item/clothing/under/S, mob/user as mob) + ..() + has_suit.verbs += /obj/item/clothing/tie/holster/verb/holster_verb + +/obj/item/clothing/tie/holster/on_removed(mob/user as mob) + has_suit.verbs -= /obj/item/clothing/tie/holster/verb/holster_verb + ..() + +//For the holster hotkey +/obj/item/clothing/tie/holster/verb/holster_verb() + set name = "Holster" + set category = "Object" + set src in usr + if(!istype(usr, /mob/living)) return + if(usr.stat) return + + var/obj/item/clothing/tie/holster/H = null + if (istype(src, /obj/item/clothing/tie/holster)) + H = src + else if (istype(src, /obj/item/clothing/under)) + var/obj/item/clothing/under/S = src + if (S.hastie) + H = S.hastie + + if (!H) + usr << "/red Something is very wrong." + + if(!H.holstered) + if(!istype(usr.get_active_hand(), /obj/item/weapon/gun)) + usr << "\blue You need your gun equiped to holster it." + return + var/obj/item/weapon/gun/W = usr.get_active_hand() + H.holster(W, usr) + else + H.unholster(usr) + /obj/item/clothing/tie/holster/armpit name = "shoulder holster" desc = "A worn-out handgun holster. Perfect for concealed carry" @@ -177,17 +313,43 @@ /obj/item/clothing/tie/storage name = "load bearing equipment" - desc = "Used to hold things when you don't have enough hands for that." + desc = "Used to hold things when you don't have enough hands." icon_state = "webbing" item_color = "webbing" var/slots = 3 - var/obj/item/weapon/storage/pockets/hold + var/obj/item/weapon/storage/internal/hold /obj/item/clothing/tie/storage/New() - hold = new /obj/item/weapon/storage/pockets(src) - hold.master_item = src + ..() + hold = new/obj/item/weapon/storage/internal(src) hold.storage_slots = slots +/obj/item/clothing/tie/storage/attack_hand(mob/user as mob) + if (has_suit) //if we are part of a suit + hold.open(user) + return + + if (hold.handle_attack_hand(user)) //otherwise interact as a regular storage item + ..(user) + +/obj/item/clothing/tie/storage/MouseDrop(obj/over_object as obj) + if (has_suit) + return + + if (hold.handle_mousedrop(usr, over_object)) + ..(over_object) + +/obj/item/clothing/tie/storage/attackby(obj/item/W as obj, mob/user as mob) + hold.attackby(W, user) + +/obj/item/clothing/tie/storage/emp_act(severity) + hold.emp_act(severity) + ..() + +/obj/item/clothing/tie/storage/hear_talk(mob/M, var/msg) + hold.hear_talk(M, msg) + ..() + /obj/item/clothing/tie/storage/attack_self(mob/user as mob) user << "You empty [src]." var/turf/T = get_turf(src) @@ -196,18 +358,6 @@ hold.remove_from_storage(I, T) src.add_fingerprint(user) -/obj/item/clothing/tie/storage/attackby(obj/item/weapon/W as obj, mob/user as mob) - hold.attackby(W,user) - src.add_fingerprint(user) - -/obj/item/weapon/storage/pockets - name = "storage" - var/master_item //item it belongs to - -/obj/item/weapon/storage/pockets/close(mob/user as mob) - ..() - loc = master_item - /obj/item/clothing/tie/storage/webbing name = "webbing" desc = "Strudy mess of synthcotton belts and buckles, ready to share your burden." @@ -321,27 +471,14 @@ item_color = "unathiharness2" slots = 2 -/obj/item/clothing/tie/storage/knifeharness/attackby(var/obj/item/O as obj, mob/user as mob) - ..() - update() - -/obj/item/clothing/tie/storage/knifeharness/proc/update() - var/count = 0 - for(var/obj/item/I in hold) - if(istype(I,/obj/item/weapon/hatchet/unathiknife)) - count++ - if(count>2) count = 2 - item_state = "unathiharness[count]" - icon_state = item_state - item_color = item_state - - if(istype(loc, /obj/item/clothing)) - var/obj/item/clothing/U = loc - if(istype(U.loc, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = U.loc - H.update_inv_w_uniform() - /obj/item/clothing/tie/storage/knifeharness/New() ..() + hold.max_combined_w_class = 4 + hold.can_hold = list("/obj/item/weapon/hatchet/unathiknife",\ + "/obj/item/weapon/kitchen/utensil/knife",\ + "/obj/item/weapon/kitchen/utensil/pknife",\ + "/obj/item/weapon/kitchenknife",\ + "/obj/item/weapon/kitchenknife/ritual") + + new /obj/item/weapon/hatchet/unathiknife(hold) new /obj/item/weapon/hatchet/unathiknife(hold) - new /obj/item/weapon/hatchet/unathiknife(hold) \ No newline at end of file diff --git a/code/modules/detectivework/detective_work.dm b/code/modules/detectivework/detective_work.dm index 725351c7..9f2667b1 100644 --- a/code/modules/detectivework/detective_work.dm +++ b/code/modules/detectivework/detective_work.dm @@ -126,331 +126,333 @@ obj/machinery/computer/forensic_scanning Topic(href,href_list) - switch(href_list["operation"]) - if("login") - var/mob/M = usr - if(istype(M,/mob/living/silicon)) - authenticated = 1 - updateDialog() - return - if (allowed(M)) - authenticated = 1 - if("logout") - authenticated = 0 - if("clear") - if(canclear) - temp = null - if("eject") - if(scanning) - scanning.loc = loc - scanning = null - else - temp = "Eject Failed: No Object" - if("insert") - var/mob/M = usr - var/obj/item/I = M.get_active_hand() - if(I && istype(I)) - if(istype(I, /obj/item/weapon/evidencebag)) - scanning = I.contents[1] - scanning.loc = src - I.overlays -= scanning - I.icon_state = "evidenceobj" + if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) + usr.set_machine(src) + switch(href_list["operation"]) + if("login") + var/mob/M = usr + if(istype(M,/mob/living/silicon)) + authenticated = 1 + updateDialog() + return + if (allowed(M)) + authenticated = 1 + if("logout") + authenticated = 0 + if("clear") + if(canclear) + temp = null + if("eject") + if(scanning) + scanning.loc = loc + scanning = null else - scanning = I + temp = "Eject Failed: No Object" + if("insert") + var/mob/M = usr + var/obj/item/I = M.get_active_hand() + if(I && istype(I)) + if(istype(I, /obj/item/weapon/evidencebag)) + scanning = I.contents[1] + scanning.loc = src + I.overlays -= scanning + I.icon_state = "evidenceobj" + else + scanning = I + M.drop_item() + I.loc = src + else + usr << "Invalid Object Rejected." + if("card") //Processing a fingerprint card. + var/mob/M = usr + var/obj/item/I = M.get_active_hand() + if(!(I && istype(I,/obj/item/weapon/f_card))) + I = card + if(I && istype(I,/obj/item/weapon/f_card)) + card = I + if(!card.fingerprints) + card.fingerprints = list() + if(card.amount > 1 || !card.fingerprints.len) + usr << "\red ERROR: No prints/too many cards." + if(card.loc == src) + card.loc = src.loc + card = null + return M.drop_item() I.loc = src - else - usr << "Invalid Object Rejected." - if("card") //Processing a fingerprint card. - var/mob/M = usr - var/obj/item/I = M.get_active_hand() - if(!(I && istype(I,/obj/item/weapon/f_card))) - I = card - if(I && istype(I,/obj/item/weapon/f_card)) - card = I - if(!card.fingerprints) - card.fingerprints = list() - if(card.amount > 1 || !card.fingerprints.len) - usr << "\red ERROR: No prints/too many cards." - if(card.loc == src) - card.loc = src.loc - card = null - return - M.drop_item() - I.loc = src - process_card() - else - usr << "\red Invalid Object Rejected." - if("database") //Viewing all records in each database - canclear = 1 - if(href_list["delete_record"]) - delete_dossier(href_list["delete_record"]) - if(href_list["delete_aux"]) - delete_record(href_list["delete_aux"]) - if((!misc || !misc.len) && (!files || !files.len)) - temp = "Database is empty." - else - if(files && files.len) - temp = "Criminal Evidence Database

        " - temp += "Consolidated data points:
        " - for(var/print in files) - var/list/file = files[print] - temp += "{[file[2]]}
        " - temp += "
        {Insert Finger Print Card (To complete a Dossier)}


        " + process_card() else - temp = "" - if(misc && misc.len) - temp += {"Auxiliary Evidence Database

        - This is where anything without fingerprints goes.

        "} - for(var/atom in misc) - var/list/data_entry = misc[atom] - temp += "{[data_entry[3]]}
        " - if("record") //Viewing a record from the "files" database. - canclear = 0 - if(files) - var/list/dossier = files[href_list["identifier"]] - if(href_list["ren"]) - var/new_title = copytext(sanitize(input("Rename to what?", "Dossier Editing", "Dossier [files.Find(href_list["identifier"])]") as null|text),1,MAX_MESSAGE_LEN) - if(new_title) - dossier[2] = new_title + usr << "\red Invalid Object Rejected." + if("database") //Viewing all records in each database + canclear = 1 + if(href_list["delete_record"]) + delete_dossier(href_list["delete_record"]) + if(href_list["delete_aux"]) + delete_record(href_list["delete_aux"]) + if((!misc || !misc.len) && (!files || !files.len)) + temp = "Database is empty." + else + if(files && files.len) + temp = "Criminal Evidence Database

        " + temp += "Consolidated data points:
        " + for(var/print in files) + var/list/file = files[print] + temp += "{[file[2]]}
        " + temp += "
        {Insert Finger Print Card (To complete a Dossier)}


        " else - usr << "Illegal or blank name." - temp = {"Criminal Evidence Database

        - Consolidated data points: [dossier[2]]
        "} - var/print_string = "Fingerprints: Print not complete!
        " - if(stringpercent(dossier[1]) <= FINGERPRINT_COMPLETE) - print_string = "Fingerprints: (80% or higher completion reached)
        [dossier[1]]
        " - temp += print_string - for(var/object in dossier) - if(object == dossier[1] || object == dossier[2]) - continue - temp += "
        " - var/list/outputs = dossier[object] - var/list/prints = outputs[1] - temp += "Object: [outputs[4]]
        " - temp += " Fingerprints:
        " - temp += "    [prints.len] Unique fingerprints found.
        " - var/complete_prints = 0 - for(var/print in prints) - if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE) - complete_prints++ - temp += "      [prints[print]]
        " - if(complete_prints) - temp += "      And [prints.len - complete_prints] unknown unique prints.
        " - else - temp += "      No prints of sufficient completeness.
        " - var/list/fibers = outputs[2] + temp = "" + if(misc && misc.len) + temp += {"Auxiliary Evidence Database

        + This is where anything without fingerprints goes.

        "} + for(var/atom in misc) + var/list/data_entry = misc[atom] + temp += "{[data_entry[3]]}
        " + if("record") //Viewing a record from the "files" database. + canclear = 0 + if(files) + var/list/dossier = files[href_list["identifier"]] + if(href_list["ren"]) + var/new_title = copytext(sanitize(input("Rename to what?", "Dossier Editing", "Dossier [files.Find(href_list["identifier"])]") as null|text),1,MAX_MESSAGE_LEN) + if(new_title) + dossier[2] = new_title + else + usr << "Illegal or blank name." + temp = {"Criminal Evidence Database

        + Consolidated data points: [dossier[2]]
        "} + var/print_string = "Fingerprints: Print not complete!
        " + if(stringpercent(dossier[1]) <= FINGERPRINT_COMPLETE) + print_string = "Fingerprints: (80% or higher completion reached)
        [dossier[1]]
        " + temp += print_string + for(var/object in dossier) + if(object == dossier[1] || object == dossier[2]) + continue + temp += "
        " + var/list/outputs = dossier[object] + var/list/prints = outputs[1] + temp += "Object: [outputs[4]]
        " + temp += " Fingerprints:
        " + temp += "    [prints.len] Unique fingerprints found.
        " + var/complete_prints = 0 + for(var/print in prints) + if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE) + complete_prints++ + temp += "      [prints[print]]
        " + if(complete_prints) + temp += "      And [prints.len - complete_prints] unknown unique prints.
        " + else + temp += "      No prints of sufficient completeness.
        " + var/list/fibers = outputs[2] + if(fibers && fibers.len) + temp += " Fibers:
        " + for(var/j = 1, j <= fibers.len, j++) + temp += "      [fibers[j]]
        " + var/list/blood = outputs[3] + if(blood && blood.len) + temp += " Blood:
        " + for(var/named in blood) + temp += "      Type: [blood[named]], DNA: [named]
        " + temp += "
        {Rename this Dossier}" + temp += "
        {Delete this Dossier}" + temp += "
        {Print}" + else + temp = "ERROR. Database not found!
        " + temp += "
        {Return}" + if("databaseprint") //Printing from the "files" database. + if(files) + var/obj/item/weapon/paper/P = new(loc) + var/list/dossier = files[href_list["identifier"]] + P.name = "\improper Database File ([dossier[2]])" + P.overlays += "paper_words" + P.info = "Criminal Evidence Database

        " + P.info += "Consolidated data points: [dossier[2]]
        " + var/print_string = "Fingerprints: Print not complete!
        " + if(stringpercent(dossier[1]) <= FINGERPRINT_COMPLETE) + print_string = "Fingerprints: (80% or higher completion reached)
        [dossier[1]]
        " + P.info += print_string + for(var/object in dossier) + if(object == dossier[1] || object == dossier[2]) + continue + P.info += "
        " + var/list/outputs = dossier[object] + var/list/prints = outputs[1] + P.info += "Object: [outputs[4]]
        " + P.info += " Fingerprints:
        " + P.info += "    [prints.len] Unique fingerprints found.
        " + var/complete_prints = 0 + for(var/print in prints) + if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE) + complete_prints++ + P.info += "      [prints[print]]
        " + if(complete_prints) + P.info += "      And [prints.len - complete_prints] unknown unique prints.
        " + else + P.info += "      No prints of sufficient completeness.
        " + var/list/fibers = outputs[2] + if(fibers && fibers.len) + P.info += " Fibers:
        " + for(var/j = 1, j <= fibers.len, j++) + P.info += "      [fibers[j]]
        " + var/list/blood = outputs[3] + if(blood && blood.len) + P.info += " Blood:
        " + for(var/named in blood) + P.info += "      Type: [blood[named]], DNA: [named]
        " + else + usr << "ERROR. Database not found!
        " + if("auxiliary") //Viewing a record from the "misc" database. + canclear = 0 + if(misc) + temp = "Auxiliary Evidence Database

        " + var/list/outputs = misc[href_list["identifier"]] + temp += "Consolidated data points: [outputs[3]]
        " + var/list/prints = outputs[4] + if(prints) + temp += " Fingerprints:
        " + temp += "    [prints.len] Unique fingerprints found.
        " + var/complete_prints = 0 + for(var/print in prints) + if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE) + complete_prints++ + temp += "      [prints[print]]
        " + if(complete_prints) + temp += "      And [prints.len - complete_prints] unknown unique prints.
        " + else + temp += "      No prints of sufficient completeness.
        " + var/list/fibers = outputs[1] if(fibers && fibers.len) temp += " Fibers:
        " - for(var/j = 1, j <= fibers.len, j++) - temp += "      [fibers[j]]
        " - var/list/blood = outputs[3] + for(var/fiber in fibers) + temp += "      [fiber]
        " + var/list/blood = outputs[2] if(blood && blood.len) temp += " Blood:
        " for(var/named in blood) temp += "      Type: [blood[named]], DNA: [named]
        " - temp += "
        {Rename this Dossier}" - temp += "
        {Delete this Dossier}" - temp += "
        {Print}" - else - temp = "ERROR. Database not found!
        " - temp += "
        {Return}" - if("databaseprint") //Printing from the "files" database. - if(files) - var/obj/item/weapon/paper/P = new(loc) - var/list/dossier = files[href_list["identifier"]] - P.name = "\improper Database File ([dossier[2]])" - P.overlays += "paper_words" - P.info = "Criminal Evidence Database

        " - P.info += "Consolidated data points: [dossier[2]]
        " - var/print_string = "Fingerprints: Print not complete!
        " - if(stringpercent(dossier[1]) <= FINGERPRINT_COMPLETE) - print_string = "Fingerprints: (80% or higher completion reached)
        [dossier[1]]
        " - P.info += print_string - for(var/object in dossier) - if(object == dossier[1] || object == dossier[2]) - continue - P.info += "
        " - var/list/outputs = dossier[object] - var/list/prints = outputs[1] - P.info += "Object: [outputs[4]]
        " - P.info += " Fingerprints:
        " - P.info += "    [prints.len] Unique fingerprints found.
        " - var/complete_prints = 0 - for(var/print in prints) - if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE) - complete_prints++ - P.info += "      [prints[print]]
        " - if(complete_prints) - P.info += "      And [prints.len - complete_prints] unknown unique prints.
        " - else - P.info += "      No prints of sufficient completeness.
        " - var/list/fibers = outputs[2] + temp += "
        {Delete This Record}" + temp += "
        {Print}" + else + temp = "ERROR. Database not found!
        " + temp += "
        {Return}" + if("auxiliaryprint") //Printing from the "misc" database. + if(misc) + var/obj/item/weapon/paper/P = new(loc) + var/list/outputs = misc[href_list["identifier"]] + P.name = "\improper Auxiliary Database File ([outputs[3]])" + P.overlays += "paper_words" + P.info = "Auxiliary Evidence Database

        " + P.info += "Consolidated data points: [outputs[3]]
        " + var/list/prints = outputs[4] + if(prints) + P.info += " Fingerprints:
        " + P.info += "    [prints.len] Unique fingerprints found.
        " + var/complete_prints = 0 + for(var/print in prints) + if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE) + complete_prints++ + P.info += "      [prints[print]]
        " + if(complete_prints) + P.info += "      And [prints.len - complete_prints] unknown unique prints.
        " + else + P.info += "      No prints of sufficient completeness.
        " + var/list/fibers = outputs[1] if(fibers && fibers.len) P.info += " Fibers:
        " - for(var/j = 1, j <= fibers.len, j++) - P.info += "      [fibers[j]]
        " - var/list/blood = outputs[3] + for(var/fiber in fibers) + P.info += "      [fiber]
        " + var/list/blood = outputs[2] if(blood && blood.len) P.info += " Blood:
        " for(var/named in blood) P.info += "      Type: [blood[named]], DNA: [named]
        " - else - usr << "ERROR. Database not found!
        " - if("auxiliary") //Viewing a record from the "misc" database. - canclear = 0 - if(misc) - temp = "Auxiliary Evidence Database

        " - var/list/outputs = misc[href_list["identifier"]] - temp += "Consolidated data points: [outputs[3]]
        " - var/list/prints = outputs[4] - if(prints) - temp += " Fingerprints:
        " - temp += "    [prints.len] Unique fingerprints found.
        " - var/complete_prints = 0 - for(var/print in prints) - if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE) - complete_prints++ - temp += "      [prints[print]]
        " - if(complete_prints) - temp += "      And [prints.len - complete_prints] unknown unique prints.
        " - else - temp += "      No prints of sufficient completeness.
        " - var/list/fibers = outputs[1] - if(fibers && fibers.len) - temp += " Fibers:
        " - for(var/fiber in fibers) - temp += "      [fiber]
        " - var/list/blood = outputs[2] - if(blood && blood.len) - temp += " Blood:
        " - for(var/named in blood) - temp += "      Type: [blood[named]], DNA: [named]
        " - temp += "
        {Delete This Record}" - temp += "
        {Print}" - else - temp = "ERROR. Database not found!
        " - temp += "
        {Return}" - if("auxiliaryprint") //Printing from the "misc" database. - if(misc) - var/obj/item/weapon/paper/P = new(loc) - var/list/outputs = misc[href_list["identifier"]] - P.name = "\improper Auxiliary Database File ([outputs[3]])" - P.overlays += "paper_words" - P.info = "Auxiliary Evidence Database

        " - P.info += "Consolidated data points: [outputs[3]]
        " - var/list/prints = outputs[4] - if(prints) - P.info += " Fingerprints:
        " - P.info += "    [prints.len] Unique fingerprints found.
        " - var/complete_prints = 0 - for(var/print in prints) - if(stringpercent(prints[print]) <= FINGERPRINT_COMPLETE) - complete_prints++ - P.info += "      [prints[print]]
        " - if(complete_prints) - P.info += "      And [prints.len - complete_prints] unknown unique prints.
        " - else - P.info += "      No prints of sufficient completeness.
        " - var/list/fibers = outputs[1] - if(fibers && fibers.len) - P.info += " Fibers:
        " - for(var/fiber in fibers) - P.info += "      [fiber]
        " - var/list/blood = outputs[2] - if(blood && blood.len) - P.info += " Blood:
        " - for(var/named in blood) - P.info += "      Type: [blood[named]], DNA: [named]
        " - else - usr << "ERROR. Database not found!
        " - if("scan") - if(istype(scanning,/obj/item/weapon/f_card)) - card = scanning - scanning = initial(scanning) - process_card() - else if(scanning) - scan_process = 3 - scan_data = "Scanning [scanning]: 25% complete" - updateDialog() - sleep(50) - if(!scan_process) - scan_data = null + else + usr << "ERROR. Database not found!
        " + if("scan") + if(istype(scanning,/obj/item/weapon/f_card)) + card = scanning + scanning = initial(scanning) + process_card() + else if(scanning) + scan_process = 3 + scan_data = "Scanning [scanning]: 25% complete" updateDialog() - return - scan_data = "Scanning [scanning]: 50% complete" - updateDialog() - scan_process = 2 - sleep(50) - if(!scan_process) - scan_data = null + sleep(50) + if(!scan_process) + scan_data = null + updateDialog() + return + scan_data = "Scanning [scanning]: 50% complete" updateDialog() - return - scan_data = "Scanning [scanning]: 75% complete" - updateDialog() - scan_process = 1 - sleep(50) - if(!scan_process) - scan_data = null + scan_process = 2 + sleep(50) + if(!scan_process) + scan_data = null + updateDialog() + return + scan_data = "Scanning [scanning]: 75% complete" updateDialog() - return + scan_process = 1 + sleep(50) + if(!scan_process) + scan_data = null + updateDialog() + return + if(scanning) + scan_process = 0 + scan_name = scanning.name + scan_data = "[scanning]

        " + if (scanning.blood_DNA) + scan_data += "Blood Found:
        " + for(var/blood in scanning.blood_DNA) + scan_data += "Blood type: [scanning.blood_DNA[blood]]\nDNA: [blood]

        " + else + scan_data += "No Blood Found

        " + if(!scanning.fingerprints) + scan_data += "No Fingerprints Found

        " + else + scan_data += "Isolated [scanning.fingerprints.len] Fingerprints. Loaded into database.
        " + add_data(scanning) + + if(!scanning.suit_fibers) + scan_data += "No Fibers/Materials Located
        " + else + scan_data += "Fibers/Materials Found:
        " + for(var/data in scanning.suit_fibers) + scan_data += "- [data]
        " + if(istype(scanning,/obj/item/device/detective_scanner) || (istype(scanning, /obj/item/device/pda) && scanning:cartridge && scanning:cartridge.access_security)) + scan_data += "
        Data transfered from \the [scanning] to Database.
        " + add_data_scanner(scanning) + else if(!scanning.fingerprints) + scan_data += "
        Add to Database?
        " + else + temp = "Scan Failed: No Object" + + + if("print") //Printing scan data + if(scan_data) + temp = "Scan Data Printed." + var/obj/item/weapon/paper/P = new(loc) + P.name = "\improper Scan Data ([scan_name])" + P.info = "[scan_data]" + P.overlays += "paper_words" + else + temp = "Print Failed: No Data" + if("erase") + scan_data = "" + if("cancel") + scan_process = 0 + if("add") //Adding an object (Manually) to the database. if(scanning) - scan_process = 0 - scan_name = scanning.name - scan_data = "[scanning]

        " - if (scanning.blood_DNA) - scan_data += "Blood Found:
        " - for(var/blood in scanning.blood_DNA) - scan_data += "Blood type: [scanning.blood_DNA[blood]]\nDNA: [blood]

        " - else - scan_data += "No Blood Found

        " - if(!scanning.fingerprints) - scan_data += "No Fingerprints Found

        " - else - scan_data += "Isolated [scanning.fingerprints.len] Fingerprints. Loaded into database.
        " - add_data(scanning) - - if(!scanning.suit_fibers) - scan_data += "No Fibers/Materials Located
        " - else - scan_data += "Fibers/Materials Found:
        " - for(var/data in scanning.suit_fibers) - scan_data += "- [data]
        " - if(istype(scanning,/obj/item/device/detective_scanner) || (istype(scanning, /obj/item/device/pda) && scanning:cartridge && scanning:cartridge.access_security)) - scan_data += "
        Data transfered from \the [scanning] to Database.
        " - add_data_scanner(scanning) - else if(!scanning.fingerprints) - scan_data += "
        Add to Database?
        " - else - temp = "Scan Failed: No Object" - - - if("print") //Printing scan data - if(scan_data) - temp = "Scan Data Printed." - var/obj/item/weapon/paper/P = new(loc) - P.name = "\improper Scan Data ([scan_name])" - P.info = "[scan_data]" - P.overlays += "paper_words" - else - temp = "Print Failed: No Data" - if("erase") - scan_data = "" - if("cancel") - scan_process = 0 - if("add") //Adding an object (Manually) to the database. - if(scanning) - add_data(scanning) - else - temp = "Data Transfer Failed: No Object." - if("rename") - if(!files || !files[href_list["identifier"]]) - temp = "ERROR: Record/Database not found!" - else - var/new_title = copytext(sanitize(input("Rename to what?", "Dossier Editing", "Dossier [files.Find(href_list["identifier"])]") as null|text),1,MAX_MESSAGE_LEN) - if(new_title) - var/list/file = files[href_list["identifier"]] - file[2] = new_title + add_data(scanning) + else + temp = "Data Transfer Failed: No Object." + if("rename") + if(!files || !files[href_list["identifier"]]) + temp = "ERROR: Record/Database not found!" + else + var/new_title = copytext(sanitize(input("Rename to what?", "Dossier Editing", "Dossier [files.Find(href_list["identifier"])]") as null|text),1,MAX_MESSAGE_LEN) + if(new_title) + var/list/file = files[href_list["identifier"]] + file[2] = new_title updateUsrDialog() ex_act() diff --git a/code/modules/detectivework/evidence.dm b/code/modules/detectivework/evidence.dm index 0c414417..7148a5af 100644 --- a/code/modules/detectivework/evidence.dm +++ b/code/modules/detectivework/evidence.dm @@ -6,7 +6,7 @@ icon = 'icons/obj/storage.dmi' icon_state = "evidenceobj" item_state = "" - w_class = 1 + w_class = 2 /obj/item/weapon/evidencebag/afterattack(obj/item/I, mob/user as mob, proximity) if(!proximity) return diff --git a/code/modules/economy/ATM.dm b/code/modules/economy/ATM.dm index 59434f9e..9eb342d3 100644 --- a/code/modules/economy/ATM.dm +++ b/code/modules/economy/ATM.dm @@ -173,6 +173,7 @@ log transactions dat += "
        " dat += "" dat += "
        \[BANNED]
        \[BANNED]
        \[IN [(available_in_days)] DAYS]
        \[IN [(available_in_days)] DAYS]
        [T.source_terminal]
        " + dat += "Print
        " if(TRANSFER_FUNDS) dat += "Account balance: $[authenticated_account.money]
        " dat += "Back

        " @@ -190,7 +191,7 @@ log transactions dat += "" dat += "" dat += "" - dat += "
        " + dat += "" dat += "" dat += "Change account security level
        " dat += "Make transfer
        " @@ -309,7 +310,9 @@ log transactions //remove the money authenticated_account.money -= amount - spawn_money(amount,src.loc) + + // spawn_money(amount,src.loc) + spawn_ewallet(amount,src.loc) //create an entry in the account transaction log var/datum/transaction/T = new() @@ -346,6 +349,49 @@ log transactions playsound(loc, 'sound/items/polaroid1.ogg', 50, 1) else playsound(loc, 'sound/items/polaroid2.ogg', 50, 1) + if ("print_transaction") + if(authenticated_account) + var/obj/item/weapon/paper/R = new(src.loc) + R.name = "Transaction logs: [authenticated_account.owner_name]" + R.info = "Transaction logs
        " + R.info += "Account holder: [authenticated_account.owner_name]
        " + R.info += "Account number: [authenticated_account.account_number]
        " + R.info += "Date and time: [worldtime2text()], [current_date_string]

        " + R.info += "Service terminal ID: [machine_id]
        " + R.info += "" + R.info += "" + R.info += "" + R.info += "" + R.info += "" + R.info += "" + R.info += "" + R.info += "" + R.info += "" + for(var/datum/transaction/T in authenticated_account.transaction_log) + R.info += "" + R.info += "" + R.info += "" + R.info += "" + R.info += "" + R.info += "" + R.info += "" + R.info += "" + R.info += "
        DateTimeTargetPurposeValueSource terminal ID
        [T.date][T.time][T.target_name][T.purpose]$[T.amount][T.source_terminal]
        " + + //stamp the paper + var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') + stampoverlay.icon_state = "paper_stamp-cent" + if(!R.stamped) + R.stamped = new + R.stamped += /obj/item/weapon/stamp + R.overlays += stampoverlay + R.stamps += "
        This paper has been stamped by the Automatic Teller Machine." + + if(prob(50)) + playsound(loc, 'sound/items/polaroid1.ogg', 50, 1) + else + playsound(loc, 'sound/items/polaroid2.ogg', 50, 1) + if("insert_card") if(!held_card) //this might happen if the user had the browser window open when somebody emagged it @@ -402,3 +448,9 @@ log transactions if(ishuman(human_user) && !human_user.get_active_hand()) human_user.put_in_hands(held_card) held_card = null + + +/obj/machinery/atm/proc/spawn_ewallet(var/sum, loc) + var/obj/item/weapon/spacecash/ewallet/E = new /obj/item/weapon/spacecash/ewallet(loc) + E.worth = sum + E.owner_name = authenticated_account.owner_name diff --git a/code/modules/economy/EFTPOS.dm b/code/modules/economy/EFTPOS.dm index 12f941bd..3812ab70 100644 --- a/code/modules/economy/EFTPOS.dm +++ b/code/modules/economy/EFTPOS.dm @@ -22,6 +22,7 @@ //create a short manual as well var/obj/item/weapon/paper/R = new(src.loc) R.name = "Steps to success: Correct EFTPOS Usage" + /* R.info += "When first setting up your EFTPOS device:" R.info += "1. Memorise your EFTPOS command code (provided with all EFTPOS devices).
        " R.info += "2. Confirm that your EFTPOS device is connected to your local accounts database. For additional assistance with this step, contact NanoTrasen IT Support
        " @@ -33,6 +34,17 @@ R.info += "4. If at this stage you wish to modify or cancel your transaction, you may simply reset (unlock) your EFTPOS device.
        " R.info += "5. Give your EFTPOS device to the customer, they must authenticate the transaction by swiping their ID card and entering their PIN number.
        " R.info += "6. If done correctly, the transaction will be logged to both accounts with the reference you have entered, the terminal ID of your EFTPOS device and the money transferred across accounts.
        " + */ + //Temptative new manual: + R.info += "First EFTPOS setup:
        " + R.info += "1. Memorise your EFTPOS command code (provided with all EFTPOS devices).
        " + R.info += "2. Connect the EFTPOS to the account in which you want to receive the funds.

        " + R.info += "When starting a new transaction:
        " + R.info += "1. Enter the amount of money you want to charge and a purpose message for the new transaction.
        " + R.info += "2. Lock the new transaction. If you want to modify or cancel the transaction, you simply have to reset your EFTPOS device.
        " + R.info += "3. Give the EFTPOS device to your customer, he/she must finish the transaction by swiping their ID card or a charge card with enough funds.
        " + R.info += "4. If everything is done correctly, the money will be transferred. To unlock the device you will have to reset the EFTPOS device.
        " + //stamp the paper var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') @@ -72,7 +84,7 @@ var/dat = "[eftpos_name]
        " dat += "This terminal is [machine_id]. Report this code when contacting NanoTrasen IT Support
        " if(transaction_locked) - dat += "Reset[transaction_paid ? "" : " (authentication required)"]

        " + dat += "Back[transaction_paid ? "" : " (authentication required)"]

        " dat += "Transaction purpose: [transaction_purpose]
        " dat += "Value: $[transaction_amount]
        " @@ -102,6 +114,36 @@ scan_card(I) else usr << "\icon[src]Unable to connect to linked account." + else if (istype(O, /obj/item/weapon/spacecash/ewallet)) + var/obj/item/weapon/spacecash/ewallet/E = O + if (linked_account) + if(!linked_account.suspended) + if(transaction_locked && !transaction_paid) + if(transaction_amount <= E.worth) + playsound(src, 'sound/machines/chime.ogg', 50, 1) + src.visible_message("\icon[src] The [src] chimes.") + transaction_paid = 1 + + //transfer the money + E.worth -= transaction_amount + linked_account.money += transaction_amount + + //create entry in the EFTPOS linked account transaction log + var/datum/transaction/T = new() + T.target_name = E.owner_name //D.owner_name + T.purpose = transaction_purpose + T.amount = transaction_amount + T.source_terminal = machine_id + T.date = current_date_string + T.time = worldtime2text() + linked_account.transaction_log.Add(T) + else + usr << "\icon[src]The charge card doesn't have that much money!" + else + usr << "\icon[src]Connected account has been suspended." + else + usr << "\icon[src]EFTPOS is not connected to an account." + else ..() @@ -143,10 +185,14 @@ transaction_amount = try_num if("toggle_lock") if(transaction_locked) - var/attempt_code = input("Enter EFTPOS access code", "Reset Transaction") as num - if(attempt_code == access_code) + if (transaction_paid) transaction_locked = 0 transaction_paid = 0 + else + var/attempt_code = input("Enter EFTPOS access code", "Reset Transaction") as num + if(attempt_code == access_code) + transaction_locked = 0 + transaction_paid = 0 else if(linked_account) transaction_locked = 1 else diff --git a/code/modules/economy/cash.dm b/code/modules/economy/cash.dm index 356015c6..c454d9dd 100644 --- a/code/modules/economy/cash.dm +++ b/code/modules/economy/cash.dm @@ -71,4 +71,16 @@ proc/spawn_money(var/sum, spawnloc) while(sum >= i) sum -= i new cash_type(spawnloc) - return \ No newline at end of file + return + +/obj/item/weapon/spacecash/ewallet + name = "Charge card" + icon_state = "efundcard" + desc = "A card that holds an amount of money." + var/owner_name = "" //So the ATM can set it so the EFTPOS can put a valid name on transactions. + +/obj/item/weapon/spacecash/ewallet/examine() + set src in view() + ..() + if (!(usr in view(2)) && usr!=src.loc) return + usr << "\blue Charge card's owner: [src.owner_name]. Credits remaining: [src.worth]." \ No newline at end of file diff --git a/code/modules/events/infestation.dm b/code/modules/events/infestation.dm index 31f4ecdc..c1a9c1cb 100644 --- a/code/modules/events/infestation.dm +++ b/code/modules/events/infestation.dm @@ -7,7 +7,7 @@ #define LOC_VAULT 6 #define LOC_CONSTR 7 #define LOC_TECH 8 -#define LOC_ASSEMBLY 9 +#define LOC_ARMOURY 9 #define VERM_MICE 0 #define VERM_LIZARDS 1 @@ -54,9 +54,9 @@ if(LOC_TECH) spawn_area_type = /area/storage/tech locstring = "technical storage" - if(LOC_ASSEMBLY) - spawn_area_type = /area/assembly/assembly_line - locstring = "the unused assembly line" + if(LOC_ARMOURY) + spawn_area_type = /area/security/armoury + locstring = "the armoury" //world << "looking for [spawn_area_type]" for(var/areapath in typesof(spawn_area_type)) @@ -83,6 +83,7 @@ vermstring = "lizards" if(VERM_SPIDERS) spawn_types = list(/obj/effect/spider/spiderling) + max_number = 3 vermstring = "spiders" spawn(0) @@ -92,7 +93,6 @@ turfs.Remove(T) num-- - if(vermin == VERM_SPIDERS) var/obj/effect/spider/spiderling/S = new(T) S.amount_grown = -1 @@ -112,7 +112,7 @@ #undef LOC_HYDRO #undef LOC_VAULT #undef LOC_TECH -#undef LOC_ASSEMBLY +#undef LOC_ARMOURY #undef VERM_MICE #undef VERM_LIZARDS diff --git a/code/modules/ext_scripts/irc.dm b/code/modules/ext_scripts/irc.dm index fc8910d7..80066521 100644 --- a/code/modules/ext_scripts/irc.dm +++ b/code/modules/ext_scripts/irc.dm @@ -7,9 +7,11 @@ else nudge_lib = "lib/nudge.so" - call(nudge_lib, "nudge")("[config.comms_password]","[config.irc_bot_host]","[channel]","[msg]") + spawn(0) + call(nudge_lib, "nudge")("[config.comms_password]","[config.irc_bot_host]","[channel]","[msg]") else - ext_python("ircbot_message.py", "[config.comms_password] [config.irc_bot_host] [channel] [msg]") + spawn(0) + ext_python("ircbot_message.py", "[config.comms_password] [config.irc_bot_host] [channel] [msg]") return /proc/send2mainirc(var/msg) @@ -26,3 +28,4 @@ /hook/startup/proc/ircNotify() send2mainirc("Server starting up on [config.server? "byond://[config.server]" : "byond://[world.address]:[world.port]"]") return 1 + diff --git a/code/modules/food/recipes_microwave.dm b/code/modules/food/recipes_microwave.dm index 3e51d032..36cd914f 100644 --- a/code/modules/food/recipes_microwave.dm +++ b/code/modules/food/recipes_microwave.dm @@ -1215,6 +1215,12 @@ I said no! ) result = /obj/item/weapon/reagent_containers/food/snacks/tofurkey +// Fuck Science! +/datum/recipe/ruinedvirusdish + items = list( + /obj/item/weapon/virusdish + ) + result = /obj/item/weapon/ruinedvirusdish ////////////////////////////////////////// // bs12 food port stuff diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index b519ee60..92b6d054 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -237,6 +237,12 @@ else ..() +/obj/item/weapon/book/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) + if(user.zone_sel.selecting == "eyes") + user.visible_message("You open up the book and show it to [M]. ", \ + " [user] opens up a book and shows it to [M]. ") + M << browse("Penned by [author].
        " + "[dat]", "window=book") + /* * Barcode Scanner @@ -247,7 +253,7 @@ icon_state ="scanner" throw_speed = 1 throw_range = 5 - w_class = 1.0 + w_class = 2.0 flags = FPRINT | TABLEPASS var/obj/machinery/librarycomp/computer // Associated computer - Modes 1 to 3 use this var/obj/item/weapon/book/book // Currently scanned book diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 14e07c3f..81165e30 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -161,28 +161,8 @@ proc/move_mining_shuttle() src.req_access = list() hacked = 1 usr << "You fried the consoles ID checking system. It's now available to everyone!" - - else if(istype(W, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, 20)) - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - var/obj/item/weapon/circuitboard/mining_shuttle/M = new /obj/item/weapon/circuitboard/mining_shuttle( A ) - for (var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.anchored = 1 - - if (src.stat & BROKEN) - user << "\blue The broken glass falls out." - new /obj/item/weapon/shard( src.loc ) - A.state = 3 - A.icon_state = "3" - else - user << "\blue You disconnect the monitor." - A.state = 4 - A.icon_state = "4" - - del(src) + else + ..() /******************************Lantern*******************************/ diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index c91bfd56..1127ed1d 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -13,7 +13,7 @@ var/list/artifact_spawn = list() // Runtime fix for geometry loading before cont opacity = 1 density = 1 blocks_air = 1 - temperature = TCMB + temperature = T0C var/mineral/mineral var/mined_ore = 0 var/last_act = 0 @@ -389,7 +389,7 @@ var/list/artifact_spawn = list() // Runtime fix for geometry loading before cont icon_state = "asteroid" oxygen = 0.01 nitrogen = 0.01 - temperature = TCMB + temperature = T0C icon_plating = "asteroid" var/dug = 0 //0 = has not yet been dug, 1 = has already been dug diff --git a/code/modules/mining/minerals.dm b/code/modules/mining/minerals.dm index af5d74d7..aa8981e7 100644 --- a/code/modules/mining/minerals.dm +++ b/code/modules/mining/minerals.dm @@ -30,37 +30,37 @@ mineral mineral/uranium name = "Uranium" - result_amount = 1 + result_amount = 5 spread_chance = 10 ore = /obj/item/weapon/ore/uranium mineral/iron name = "Iron" - result_amount = 1 + result_amount = 5 spread_chance = 25 ore = /obj/item/weapon/ore/iron mineral/diamond name = "Diamond" - result_amount = 1 + result_amount = 5 spread_chance = 10 ore = /obj/item/weapon/ore/diamond mineral/gold name = "Gold" - result_amount = 1 + result_amount = 5 spread_chance = 10 ore = /obj/item/weapon/ore/gold mineral/silver name = "Silver" - result_amount = 1 + result_amount = 5 spread_chance = 10 ore = /obj/item/weapon/ore/silver mineral/plasma name = "Plasma" - result_amount = 1 + result_amount = 5 spread_chance = 25 ore = /obj/item/weapon/ore/plasma diff --git a/code/modules/mining/satchel_ore_boxdm.dm b/code/modules/mining/satchel_ore_boxdm.dm index 4a0c9a61..ebbf0ec6 100644 --- a/code/modules/mining/satchel_ore_boxdm.dm +++ b/code/modules/mining/satchel_ore_boxdm.dm @@ -10,7 +10,8 @@ /obj/structure/ore_box/attackby(obj/item/weapon/W as obj, mob/user as mob) if (istype(W, /obj/item/weapon/ore)) - src.contents += W; + user.u_equip(W) + src.contents += W if (istype(W, /obj/item/weapon/storage)) var/obj/item/weapon/storage/S = W S.hide_from(usr) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 756989a7..e11c7b95 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -69,6 +69,15 @@ ..() + +/mob/dead/observer/Topic(href, href_list) + if (href_list["track"]) + var/mob/target = locate(href_list["track"]) in mob_list + if(target) + ManualFollow(target) + + + /mob/dead/attackby(obj/item/W, mob/user) if(istype(W,/obj/item/weapon/tome)) var/mob/dead/M = src diff --git a/code/modules/mob/death.dm b/code/modules/mob/death.dm index 86f7ce0b..797715c3 100644 --- a/code/modules/mob/death.dm +++ b/code/modules/mob/death.dm @@ -48,6 +48,12 @@ /mob/proc/death(gibbed) + + //Quick fix for corpses kept propped up in chairs. ~Z + drop_r_hand() + drop_l_hand() + //End of fix. + timeofdeath = world.time living_mob_list -= src diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 2afc2259..281933fb 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -39,12 +39,30 @@ // Type 1 (Visual) emotes are sent to anyone in view of the item if (m_type & 1) for (var/mob/O in viewers(src, null)) + + if(O.status_flags & PASSEMOTES) + + for(var/obj/item/weapon/holder/H in O.contents) + H.show_message(message, m_type) + + for(var/mob/living/M in O.contents) + M.show_message(message, m_type) + O.show_message(message, m_type) // Type 2 (Audible) emotes are sent to anyone in hear range // of the *LOCATION* -- this is important for pAIs to be heard else if (m_type & 2) for (var/mob/O in hearers(get_turf(src), null)) + + if(O.status_flags & PASSEMOTES) + + for(var/obj/item/weapon/holder/H in O.contents) + H.show_message(message, m_type) + + for(var/mob/living/M in O.contents) + M.show_message(message, m_type) + O.show_message(message, m_type) /mob/proc/emote_dead(var/message) diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm new file mode 100644 index 00000000..1853826f --- /dev/null +++ b/code/modules/mob/hear_say.dm @@ -0,0 +1,162 @@ +// At minimum every mob has a hear_say proc. + +/mob/proc/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "",var/italics = 0, var/mob/speaker = null) + if(!client) + return + + if(sleeping || stat == 1) + hear_sleep(message) + return + + var/style = "body" + if(!say_understands(speaker,language)) + if(istype(speaker,/mob/living/simple_animal)) + var/mob/living/simple_animal/S = speaker + message = pick(S.speak) + else + message = stars(message) + + if(language) + verb = language.speech_verb + style = language.colour + + var/speaker_name = speaker.name + if(istype(speaker, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = speaker + speaker_name = H.GetVoice() + + if(italics) + message = "[message]" + + var/track = null + if(istype(src, /mob/dead/observer)) + if(italics && client.prefs.toggles & CHAT_GHOSTRADIO) + return + if(speaker_name != speaker.real_name && speaker.real_name) + speaker_name = "[speaker.real_name] ([speaker_name])" + track = "(follow) " + if(client.prefs.toggles & CHAT_GHOSTEARS && speaker in view(src)) + message = "[message]" + + if(sdisabilities & DEAF || ear_deaf) + if(speaker == src) + src << "You cannot hear yourself speak!" + else + src << "[speaker_name][alt_name] talks but you cannot hear them." + else + src << "[speaker_name][alt_name] [track][verb], \"[message]\"" + + +/mob/proc/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="") + + if(!client) + return + + if(sleeping || stat==1) //If unconscious or sleeping + hear_sleep(message) + return + + var/track = null + + var/style = "body" + + if(!say_understands(speaker,language)) + if(istype(speaker,/mob/living/simple_animal)) + var/mob/living/simple_animal/S = speaker + message = pick(S.speak) + else + message = stars(message) + + if(language) + verb = language.speech_verb + style = language.colour + + + + if(hard_to_hear) + message = stars(message) + + var/speaker_name = speaker.name + + if(vname) + speaker_name = vname + + if(istype(speaker, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = speaker + if(H.voice) + speaker_name = H.voice + + if(hard_to_hear) + speaker_name = "unknown" + + var/changed_voice + + if(istype(src, /mob/living/silicon/ai) && !hard_to_hear) + var/jobname // the mob's "job" + var/mob/living/carbon/human/impersonating //The crewmember being impersonated, if any. + + if (ishuman(speaker)) + var/mob/living/carbon/human/H = speaker + + if((H.wear_id && istype(H.wear_id,/obj/item/weapon/card/id/syndicate)) && (H.wear_mask && istype(H.wear_mask,/obj/item/clothing/mask/gas/voice))) + + changed_voice = 1 + var/mob/living/carbon/human/I = locate(speaker_name) + + if(I) + impersonating = I + jobname = impersonating.get_assignment() + else + jobname = "Unknown" + else + jobname = H.get_assignment() + + else if (iscarbon(speaker)) // Nonhuman carbon mob + jobname = "No id" + else if (isAI(speaker)) + jobname = "AI" + else if (isrobot(speaker)) + jobname = "Cyborg" + else if (istype(speaker, /mob/living/silicon/pai)) + jobname = "Personal AI" + else + jobname = "Unknown" + + if(changed_voice) + if(impersonating) + track = "[speaker_name] ([jobname])" + else + track = "[speaker_name] ([jobname])" + else + track = "[speaker_name] ([jobname])" + + if(istype(src, /mob/dead/observer)) + if(speaker_name != speaker.real_name && !isAI(speaker)) //Announce computer and various stuff that broadcasts doesn't use it's real name but AI's can't pretend to be other mobs. + speaker_name = "[speaker.real_name] ([speaker_name])" + track = "[speaker_name] (follow)" + + if(sdisabilities & DEAF || ear_deaf) + if(prob(20)) + src << "You feel your headset vibrate but can hear nothing from it!" + else if(track) + src << "[part_a][track][part_b][verb], \"[message]\"" + else + src << "[part_a][speaker_name][part_b][verb], \"[message]\"" + +/mob/proc/hear_sleep(var/message) + var/heard = "" + if(prob(15)) + var/list/punctuation = list(",", "!", ".", ";", "?") + var/list/messages = text2list(message, " ") + var/R = rand(1, messages.len) + var/heardword = messages[R] + if(copytext(heardword,1, 1) in punctuation) + heardword = copytext(heardword,2) + if(copytext(heardword,-1) in punctuation) + heardword = copytext(heardword,1,lentext(heardword)) + heard = "...You hear something about...[heardword]" + + else + heard = "...You almost hear someone talking..." + + src << heard diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm new file mode 100644 index 00000000..a31c958b --- /dev/null +++ b/code/modules/mob/holder.dm @@ -0,0 +1,51 @@ +//Helper object for picking dionaea (and other creatures) up. +/obj/item/weapon/holder + name = "holder" + desc = "You shouldn't ever see this." + icon = 'icons/obj/objects.dmi' + slot_flags = SLOT_HEAD + +/obj/item/weapon/holder/New() + ..() + processing_objects.Add(src) + +/obj/item/weapon/holder/Del() + processing_objects.Remove(src) + ..() + +/obj/item/weapon/holder/process() + + if(istype(loc,/turf) || !(contents.len)) + + for(var/mob/M in contents) + + var/atom/movable/mob_container + mob_container = M + mob_container.forceMove(get_turf(src)) + M.reset_view() + + del(src) + +/obj/item/weapon/holder/attackby(obj/item/weapon/W as obj, mob/user as mob) + for(var/mob/M in src.contents) + M.attackby(W,user) + +/obj/item/weapon/holder/proc/show_message(var/message, var/m_type) + for(var/mob/living/M in contents) + M.show_message(message,m_type) + +//Mob specific holders. + +/obj/item/weapon/holder/diona + + name = "diona nymph" + desc = "It's a tiny plant critter." + icon_state = "nymph" + origin_tech = "magnets=3;biotech=5" + +/obj/item/weapon/holder/drone + + name = "maintenance drone" + desc = "It's a small maintenance robot." + icon_state = "drone" + origin_tech = "magnets=3;engineering=5" \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 8ce2c6f4..272a9186 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -58,7 +58,7 @@ /mob/living/carbon/alien/proc/handle_environment(var/datum/gas_mixture/environment) - //If there are alien weeds on the ground then heal if needed or give some toxins + //If there are alien weeds on the ground then heal if needed or give some plasma if(locate(/obj/effect/alien/weeds) in loc) if(health >= maxHealth - getCloneLoss()) adjustToxLoss(plasma_rate) diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm index 14609671..061e6cdc 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/life.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/life.dm @@ -383,13 +383,13 @@ sight |= SEE_MOBS sight |= SEE_OBJS see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM + see_invisible = SEE_INVISIBLE_LEVEL_TWO else if (stat != 2) sight |= SEE_MOBS sight &= ~SEE_TURFS sight &= ~SEE_OBJS see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM + see_invisible = SEE_INVISIBLE_LEVEL_TWO if (healths) if (stat != 2) diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index 861985dc..a9cc82d5 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -298,13 +298,13 @@ FUCK YOU MORE FAT CODE -Hawk*/ sight |= SEE_MOBS sight |= SEE_OBJS see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM + see_invisible = SEE_INVISIBLE_LEVEL_TWO else if (stat != 2) sight |= SEE_MOBS sight &= ~SEE_TURFS sight &= ~SEE_OBJS see_in_dark = 4 - see_invisible = SEE_INVISIBLE_MINIMUM + see_invisible = SEE_INVISIBLE_LEVEL_TWO if (healths) if (stat != 2) diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 1497648c..2b903433 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -5,7 +5,7 @@ icon_state = "brain2" flags = TABLEPASS force = 1.0 - w_class = 1.0 + w_class = 2.0 throwforce = 1.0 throw_speed = 3 throw_range = 5 diff --git a/code/modules/mob/living/carbon/brain/life.dm b/code/modules/mob/living/carbon/brain/life.dm index d490dde9..a704eede 100644 --- a/code/modules/mob/living/carbon/brain/life.dm +++ b/code/modules/mob/living/carbon/brain/life.dm @@ -210,7 +210,7 @@ sight |= SEE_MOBS sight |= SEE_OBJS see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM + see_invisible = SEE_INVISIBLE_LEVEL_TWO else if (stat != 2) sight &= ~SEE_TURFS sight &= ~SEE_MOBS diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 1434ffde..7785b9ea 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -195,17 +195,22 @@ if (istype(src,/mob/living/carbon/human) && src:w_uniform) var/mob/living/carbon/human/H = src H.w_uniform.add_fingerprint(M) - src.sleeping = max(0,src.sleeping-5) - if(src.sleeping == 0) - src.resting = 0 + + if(lying) + src.sleeping = max(0,src.sleeping-5) + if(src.sleeping == 0) + src.resting = 0 + M.visible_message("[M] shakes [src] trying to wake [t_him] up!", \ + "You shake [src] trying to wake [t_him] up!") + else + M.visible_message("[M] hugs [src] to make [t_him] feel better!", \ + "You hug [src] to make [t_him] feel better!") + AdjustParalysis(-3) AdjustStunned(-3) AdjustWeakened(-3) + playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - M.visible_message( \ - "\blue [M] shakes [src] trying to wake [t_him] up!", \ - "\blue You shake [src] trying to wake [t_him] up!", \ - ) /mob/living/carbon/proc/eyecheck() return 0 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 47c67dff..d1e42f06 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -12,39 +12,40 @@ real_name = "Test Dummy" status_flags = GODMODE|CANPUSH -/mob/living/carbon/human/skrell/New() +/mob/living/carbon/human/skrell/New(var/new_loc) h_style = "Skrell Male Tentacles" - set_species("Skrell") - ..() + ..(new_loc, "Skrell") -/mob/living/carbon/human/tajaran/New() +/mob/living/carbon/human/tajaran/New(var/new_loc) h_style = "Tajaran Ears" - set_species("Tajaran") - ..() + ..(new_loc, "Tajaran") -/mob/living/carbon/human/unathi/New() +/mob/living/carbon/human/unathi/New(var/new_loc) h_style = "Unathi Horns" - set_species("Unathi") - ..() + ..(new_loc, "Unathi") -/mob/living/carbon/human/vox/New() +/mob/living/carbon/human/vox/New(var/new_loc) h_style = "Short Vox Quills" - set_species("Vox") - ..() + ..(new_loc, "Vox") -/mob/living/carbon/human/diona/New() - species = new /datum/species/diona(src) - ..() +/mob/living/carbon/human/voxarmalis/New(var/new_loc) + h_style = "Bald" + ..(new_loc, "Vox Armalis") -/mob/living/carbon/human/machine/New() +/mob/living/carbon/human/diona/New(var/new_loc) + ..(new_loc, "Diona") + +/mob/living/carbon/human/machine/New(var/new_loc) h_style = "blue IPC screen" - set_species("Machine") - ..() + ..(new_loc, "Machine") -/mob/living/carbon/human/New() +/mob/living/carbon/human/New(var/new_loc, var/new_species = null) if(!species) - set_species() + if(new_species) + set_species(new_species) + else + set_species() var/datum/reagents/R = new/datum/reagents(1000) reagents = R @@ -63,7 +64,7 @@ hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank") hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank") hud_list[STATUS_HUD_OOC] = image('icons/mob/hud.dmi', src, "hudhealthy") - + ..() @@ -71,7 +72,6 @@ dna.real_name = real_name prev_gender = gender // Debug for plural genders - make_organs() make_blood() /mob/living/carbon/human/Bump(atom/movable/AM as mob|obj, yes) @@ -99,6 +99,18 @@ now_pushing = 0 return + //Leaping mobs just land on the tile, no pushing, no anything. + if(status_flags & LEAPING) + loc = tmob.loc + status_flags &= ~LEAPING + now_pushing = 0 + return + + if(istype(tmob,/mob/living/silicon/robot/drone)) //I have no idea why the hell this isn't already happening. How do mice do it? + loc = tmob.loc + now_pushing = 0 + return + //BubbleWrap: people in handcuffs are always switched around as if they were on 'help' intent to prevent a person being pulled from being seperated from their puller if((tmob.a_intent == "help" || tmob.restrained()) && (a_intent == "help" || src.restrained()) && tmob.canmove && canmove) // mutual brohugs all around! var/turf/oldloc = loc @@ -391,6 +403,9 @@ /mob/living/carbon/human/show_inv(mob/user as mob) + var/obj/item/clothing/under/suit = null + if (istype(w_uniform, /obj/item/clothing/under)) + suit = w_uniform user.set_machine(src) var/dat = {" @@ -405,21 +420,22 @@
        Right Ear: [(r_ear ? r_ear : "Nothing")]
        Head: [(head ? head : "Nothing")]
        Shoes: [(shoes ? shoes : "Nothing")] -
        Belt: [(belt ? belt : "Nothing")] -
        Uniform: [(w_uniform ? w_uniform : "Nothing")] +
        Belt: [(belt ? belt : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(belt, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")] +
        Uniform: [(w_uniform ? w_uniform : "Nothing")] [(suit) ? ((suit.has_sensor == 1) ? text(" Sensors", src) : "") :]
        (Exo)Suit: [(wear_suit ? wear_suit : "Nothing")]
        Back: [(back ? back : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")]
        ID: [(wear_id ? wear_id : "Nothing")] -
        Suit Storage: [(s_store ? s_store : "Nothing")] +
        Suit Storage: [(s_store ? s_store : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(s_store, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")]
        [(handcuffed ? text("Handcuffed") : text("Not Handcuffed"))]
        [(legcuffed ? text("Legcuffed") : text(""))] +
        [(suit) ? ((suit.hastie) ? text(" Remove Accessory", src) : "") :]
        [(internal ? text("Remove Internal") : "")]
        Remove Splints
        Empty Pockets
        Refresh
        Close
        "} - user << browse(dat, text("window=mob[name];size=340x480")) + user << browse(dat, text("window=mob[name];size=340x540")) onclose(user, "mob[name]") return @@ -860,6 +876,10 @@ return /mob/living/carbon/human/proc/vomit() + + if(species.flags & IS_SYNTHETIC) + return //Machines don't throw up. + if(!lastpuke) lastpuke = 1 src << "You feel nauseous..." @@ -1202,7 +1222,7 @@ else usr << "\blue [self ? "Your" : "[src]'s"] pulse is [src.get_pulse(GETPULSE_HAND)]." -/mob/living/carbon/human/proc/set_species(var/new_species) +/mob/living/carbon/human/proc/set_species(var/new_species, var/force_organs) if(!dna) if(!new_species) @@ -1221,6 +1241,9 @@ species = all_species[new_species] + if(force_organs || !organs || !organs.len) + species.create_organs(src) + if(species.language) add_language(species.language) @@ -1287,3 +1310,124 @@ W.update_icon() W.message = message W.add_fingerprint(src) + +/mob/living/carbon/human/can_inject(var/mob/user, var/error_msg, var/target_zone) + . = 1 + + if(!user) + target_zone = pick("chest","chest","chest","left leg","right leg","left arm", "right arm", "head") + else if(!target_zone) + target_zone = user.zone_sel.selecting + + switch(target_zone) + if("head") + if(head && head.flags & THICKMATERIAL) + . = 0 + else + if(wear_suit && wear_suit.flags & THICKMATERIAL) + . = 0 + if(!. && error_msg && user) + // Might need re-wording. + user << "There is no exposed flesh or thin material [target_zone == "head" ? "on their head" : "on their body"] to inject into." + + +//Putting a couple of procs here that I don't know where else to dump. +//Mostly going to be used for Vox and Vox Armalis, but other human mobs might like them (for adminbuse). + +/mob/living/carbon/human/proc/leap() + set category = "IC" + set name = "Leap" + set desc = "Leap at a target and grab them aggressively." + + if(last_special > world.time) + return + + if(stat || paralysis || stunned || weakened || lying) + src << "You cannot leap in your current state." + return + + var/list/choices = list() + for(var/mob/living/M in view(6,src)) + if(!istype(M,/mob/living/silicon)) + choices += M + choices -= src + + var/mob/living/T = input(src,"Who do you wish to leap at?") in null|choices + + if(!T || !src || src.stat) return + + if(get_dist(get_turf(T), get_turf(src)) > 6) return + + last_special = world.time + 100 + status_flags |= LEAPING + + src.visible_message("\The [src] leaps at [T]!") + src.throw_at(get_step(get_turf(T),get_turf(src)), 5, 1) + playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1) + + sleep(5) + + if(status_flags & LEAPING) status_flags &= ~LEAPING + + if(!src.Adjacent(T)) + src << "\red You miss!" + return + + T.Weaken(5) + + var/use_hand = "left" + if(l_hand) + if(r_hand) + src << "\red You need to have one hand free to grab someone." + return + else + use_hand = "right" + + src.visible_message("\The [src] seizes [T] aggressively!") + + var/obj/item/weapon/grab/G = new(src,T) + if(use_hand == "left") + l_hand = G + else + r_hand = G + + G.state = GRAB_AGGRESSIVE + G.icon_state = "grabbed1" + G.synch() + +/mob/living/carbon/human/proc/gut() + set category = "IC" + set name = "Gut" + set desc = "While grabbing someone aggressively, rip their guts out or tear them apart." + + if(last_special > world.time) + return + + if(stat || paralysis || stunned || weakened || lying) + src << "\red You cannot do that in your current state." + return + + var/obj/item/weapon/grab/G = locate() in src + if(!G || !istype(G)) + src << "\red You are not grabbing anyone." + return + + if(G.state < GRAB_AGGRESSIVE) + src << "\red You must have an aggressive grab to gut your prey!" + return + + last_special = world.time + 50 + + visible_message("\The [src] rips viciously at \the [G.affecting]'s body with its claws!") + + if(istype(G.affecting,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = G.affecting + H.apply_damage(50,BRUTE) + if(H.stat == 2) + H.gib() + else + var/mob/living/M = G.affecting + if(!istype(M)) return //wut + M.apply_damage(50,BRUTE) + if(M.stat == 2) + M.gib() diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index d4878041..4fbd84b7 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -73,6 +73,10 @@ /mob/living/carbon/human/adjustCloneLoss(var/amount) ..() + + if(species.flags & IS_SYNTHETIC) + return + var/heal_prob = max(0, 80 - getCloneLoss()) var/mut_prob = min(80, getCloneLoss()+10) if (amount > 0) @@ -142,6 +146,7 @@ UpdateDamageIcon() hud_updateflag |= 1 << HEALTH_HUD updatehealth() + speech_problem_flag = 1 //Heal MANY external organs, in random order @@ -163,6 +168,7 @@ parts -= picked updatehealth() hud_updateflag |= 1 << HEALTH_HUD + speech_problem_flag = 1 if(update) UpdateDamageIcon() // damage MANY external organs, in random order diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index e5c14fa5..caea7519 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -52,7 +52,7 @@ emp_act return -1 // complete projectile permutation if(check_shields(P.damage, "the [P.name]")) - P.on_hit(src, 2) + P.on_hit(src, 2, def_zone) return 2 //BEGIN BOOK'S TASER NERF. diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 4349ac32..82374655 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -18,12 +18,18 @@ var/s_tone = 0 //Skin tone + //Skin colour + var/r_skin = 0 + var/g_skin = 0 + var/b_skin = 0 + var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup var/age = 30 //Player's age (pure fluff) var/b_type = "A+" //Player's bloodtype var/underwear = 1 //Which underwear the player wants + var/undershirt = 0 //Which undershirt the player wants. var/backbag = 2 //Which backpack type the player has chosen. Nothing, Satchel or Backpack. //Equipment slots @@ -48,6 +54,10 @@ var/icon/stand_icon = null var/icon/lying_icon = null + var/voice = "" //Instead of new say code calling GetVoice() over and over and over, we're just going to ask this variable, which gets updated in Life() + + var/speech_problem_flag = 0 + var/miming = null //Toggle for the mime's abilities. var/special_voice = "" // For changing our voice. Used by a symptom. diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 7ebe021b..2653afcb 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -388,11 +388,14 @@ if(count == 0) del(src) return + if("sensor") + if (! target.w_uniform ) + del(src) if("internal") if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && istype(target.back, /obj/item/weapon/tank) && !( target.internal )) ) && !( target.internal ))) del(src) - var/list/L = list( "syringe", "pill", "drink", "dnainjector", "fuel") + var/list/L = list( "syringe", "pill", "drink", "dnainjector", "fuel", "sensor", "internal", "tie") if ((item && !( L.Find(place) ))) if(isrobot(source) && place != "handcuff") del(src) @@ -508,6 +511,17 @@ return else message = "\red [source] is trying to take off \a [target.w_uniform] from [target]'s body!" + if("tie") + var/obj/item/clothing/under/suit = target.w_uniform + target.attack_log += text("\[[time_stamp()]\] Has had their accessory ([suit.hastie]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) accessory ([suit.hastie])") + if(istype(suit.hastie, /obj/item/clothing/tie/holobadge) || istype(suit.hastie, /obj/item/clothing/tie/medal)) + for(var/mob/M in viewers(target, null)) + M.show_message("\red [source] tears off \the [suit.hastie] from [target]'s suit!" , 1) + done() + return + else + message = "\red [source] is trying to take off \a [suit.hastie] from [target]'s suit!" if("s_store") target.attack_log += text("\[[time_stamp()]\] Has had their suit storage item ([target.s_store]) removed by [source.name] ([source.ckey])") source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) suit storage item ([target.s_store])") @@ -537,6 +551,14 @@ message = "\red [source] is trying to set on [target]'s internals." if("splints") message = text("\red [] is trying to remove []'s splints!", source, target) + if("sensor") + target.attack_log += text("\[[time_stamp()]\] Has had their sensors toggled by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to toggle [target.name]'s ([target.ckey]) sensors") + var/obj/item/clothing/under/suit = target.w_uniform + if (suit.has_sensor >= 2) + source << "The controls are locked." + return + message = "\red [source] is trying to set [target]'s suit sensors!" for(var/mob/M in viewers(target, null)) M.show_message(message, 1) @@ -624,6 +646,19 @@ It can still be worn/put on as normal. slot_to_process = slot_wear_suit if (target.wear_suit && target.wear_suit.canremove) strip_item = target.wear_suit + if("tie") + var/obj/item/clothing/under/suit = target.w_uniform + //var/obj/item/clothing/tie/tie = suit.hastie + /*if(tie) + if (istype(tie,/obj/item/clothing/tie/storage)) + var/obj/item/clothing/tie/storage/W = tie + if (W.hold) + W.hold.close(usr) + usr.put_in_hands(tie) + suit.hastie = null*/ + suit.hastie.on_removed(usr) + suit.hastie = null + target.update_inv_w_uniform() if("id") slot_to_process = slot_wear_id if (target.wear_id) @@ -675,8 +710,20 @@ It can still be worn/put on as normal. O.show_message("\red [source] injects [target] with the DNA Injector!", 1) S.inuse = 0 if("pockets") - slot_to_process = slot_l_store - strip_item = target.l_store //We'll do both + if (!item || (target.l_store && target.r_store)) // Only empty pockets when hand is empty or both pockets are full + slot_to_process = slot_l_store + strip_item = target.l_store //We'll do both + else if (target.l_store) + slot_to_process = slot_r_store + else + slot_to_process = slot_l_store + if("sensor") + var/obj/item/clothing/under/suit = target.w_uniform + if (suit) + if(suit.has_sensor >= 2) + source << "The controls are locked." + else + suit.set_sensors(source) if("internal") if (target.internal) target.internal.add_fingerprint(source) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index bd9cd0de..029dd3ce 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -66,6 +66,8 @@ if(life_tick%30==15) hud_updateflag = 1022 + voice = GetVoice() + //No need to update all of these procs if the guy is dead. if(stat != DEAD && !in_stasis) if(air_master.current_cycle%4==2 || failed_last_breath) //First, resolve location and get a breath @@ -143,7 +145,6 @@ return ONE_ATMOSPHERE - pressure_difference /mob/living/carbon/human - proc/handle_disabilities() if (disabilities & EPILEPSY) if ((prob(1) && paralysis < 1)) @@ -161,6 +162,7 @@ emote("cough") return if (disabilities & TOURETTES) + speech_problem_flag = 1 if ((prob(10) && paralysis <= 1)) Stun(10) spawn( 0 ) @@ -178,6 +180,7 @@ pixel_y = old_y return if (disabilities & NERVOUS) + speech_problem_flag = 1 if (prob(10)) stuttering = max(10, stuttering) // No. -- cib @@ -222,6 +225,9 @@ proc/handle_mutations_and_radiation() + if(species.flags & IS_SYNTHETIC) //Robots don't suffer from mutations or radloss. + return + if(getFireLoss()) if((COLD_RESISTANCE in mutations) || (prob(1))) heal_organ_damage(0,1) @@ -232,6 +238,7 @@ if(!gene.block) continue if(gene.is_active(src)) + speech_problem_flag = 1 gene.OnMobLife(src) if (radiation) @@ -245,6 +252,7 @@ radiation = 0 else + if(species.flags & RAD_ABSORB) var/rads = radiation/25 radiation -= rads @@ -300,9 +308,11 @@ var/datum/gas_mixture/environment = loc.return_air() var/datum/gas_mixture/breath + // HACK NEED CHANGING LATER - if(health < config.health_threshold_crit) + if(health < config.health_threshold_crit && !reagents.has_reagent("inaprovaline")) losebreath++ + if(losebreath>0) //Suffocating so do not take a breath losebreath-- if (prob(10)) //Gasp per 10 ticks? Sounds about right. @@ -410,8 +420,6 @@ return if(!breath || (breath.total_moles() == 0) || suiciding) - if(reagents.has_reagent("inaprovaline")) - return if(suiciding) adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster failed_last_breath = 1 @@ -428,111 +436,162 @@ return 0 - var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa - //var/safe_oxygen_max = 140 // Maximum safe partial pressure of O2, in kPa (Not used for now) - var/safe_co2_max = 10 // Yes it's an arbitrary value who cares? + var/safe_pressure_min = 16 // Minimum safe partial pressure of breathable gas in kPa + //var/safe_pressure_max = 140 // Maximum safe partial pressure of breathable gas in kPa (Not used for now) + var/safe_exhaled_max = 10 // Yes it's an arbitrary value who cares? var/safe_toxins_max = 0.005 var/SA_para_min = 1 var/SA_sleep_min = 5 - var/oxygen_used = 0 - var/nitrogen_used = 0 + var/inhaled_gas_used = 0 + var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME - var/vox_oxygen_max = 1 // For vox. - //Partial pressure of the O2 in our breath - var/O2_pp = (breath.oxygen/breath.total_moles())*breath_pressure - // Same, but for the toxins - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure - // And CO2, lets say a PP of more than 10 will be bad (It's a little less really, but eh, being passed out all round aint no fun) - var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*breath_pressure // Tweaking to fit the hacky bullshit I've done with atmo -- TLE - //var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*0.5 // The default pressure value - // Nitrogen, for Vox. - var/Nitrogen_pp = (breath.nitrogen/breath.total_moles())*breath_pressure + var/inhaling + var/exhaling + var/poison + var/no_exhale - if(O2_pp < safe_oxygen_min && species.name != "Vox") // Too little oxygen + switch(species.breath_type) + if("nitrogen") + inhaling = breath.nitrogen + if("plasma") + inhaling = breath.toxins + if("C02") + inhaling = breath.carbon_dioxide + else + inhaling = breath.oxygen + + switch(species.poison_type) + if("oxygen") + poison = breath.oxygen + if("nitrogen") + poison = breath.nitrogen + if("C02") + poison = breath.carbon_dioxide + else + poison = breath.toxins + + switch(species.exhale_type) + if("C02") + exhaling = breath.carbon_dioxide + if("oxygen") + exhaling = breath.oxygen + if("nitrogen") + exhaling = breath.nitrogen + if("plasma") + exhaling = breath.toxins + else + no_exhale = 1 + + var/inhale_pp = (inhaling/breath.total_moles())*breath_pressure + var/toxins_pp = (poison/breath.total_moles())*breath_pressure + var/exhaled_pp = (exhaling/breath.total_moles())*breath_pressure + + if(inhale_pp < safe_pressure_min) if(prob(20)) spawn(0) emote("gasp") - if(O2_pp > 0) - var/ratio = safe_oxygen_min/O2_pp - adjustOxyLoss(min(5*ratio, HUMAN_MAX_OXYLOSS)) // Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!) + if(inhale_pp > 0) + var/ratio = inhale_pp/safe_pressure_min + + // Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!) + adjustOxyLoss(min(5*(1 - ratio), HUMAN_MAX_OXYLOSS)) failed_last_breath = 1 - oxygen_used = breath.oxygen*ratio/6 + inhaled_gas_used = inhaling*ratio/6 + else + adjustOxyLoss(HUMAN_MAX_OXYLOSS) failed_last_breath = 1 - oxygen_alert = max(oxygen_alert, 1) - /*else if (O2_pp > safe_oxygen_max) // Too much oxygen (commented this out for now, I'll deal with pressure damage elsewhere I suppose) - spawn(0) emote("cough") - var/ratio = O2_pp/safe_oxygen_max - oxyloss += 5*ratio - oxygen_used = breath.oxygen*ratio/6 - oxygen_alert = max(oxygen_alert, 1)*/ - else if(Nitrogen_pp < safe_oxygen_min && species.name == "Vox") //Vox breathe nitrogen, not oxygen. - if(prob(20)) - spawn(0) emote("gasp") - if(Nitrogen_pp > 0) - var/ratio = safe_oxygen_min/Nitrogen_pp - adjustOxyLoss(min(5*ratio, HUMAN_MAX_OXYLOSS)) - failed_last_breath = 1 - nitrogen_used = breath.nitrogen*ratio/6 - else - adjustOxyLoss(HUMAN_MAX_OXYLOSS) - failed_last_breath = 1 oxygen_alert = max(oxygen_alert, 1) - else // We're in safe limits + else + // We're in safe limits failed_last_breath = 0 adjustOxyLoss(-5) - oxygen_used = breath.oxygen/6 + inhaled_gas_used = inhaling/6 oxygen_alert = 0 - breath.oxygen -= oxygen_used - breath.nitrogen -= nitrogen_used - breath.carbon_dioxide += oxygen_used + switch(species.breath_type) + if("nitrogen") + breath.nitrogen -= inhaled_gas_used + else + breath.oxygen -= inhaled_gas_used - //CO2 does not affect failed_last_breath. So if there was enough oxygen in the air but too much co2, this will hurt you, but only once per 4 ticks, instead of once per tick. - if(CO2_pp > safe_co2_max) - if(!co2overloadtime) // If it's the first breath with too much CO2 in it, lets start a counter, then have them pass out after 12s or so. + if(!no_exhale) + switch(species.exhale_type) + if("oxygen") + breath.oxygen += inhaled_gas_used + if("nitrogen") + breath.nitrogen += inhaled_gas_used + if("plasma") + breath.toxins += inhaled_gas_used + if("C02") + breath.carbon_dioxide += inhaled_gas_used + + // CO2 does not affect failed_last_breath. So if there was enough oxygen in the air but too much co2, + // this will hurt you, but only once per 4 ticks, instead of once per tick. + + if(exhaled_pp > safe_exhaled_max) + + // If it's the first breath with too much CO2 in it, lets start a counter, + // then have them pass out after 12s or so. + if(!co2overloadtime) co2overloadtime = world.time + else if(world.time - co2overloadtime > 120) + + // Lets hurt em a little, let them know we mean business Paralyse(3) - adjustOxyLoss(3) // Lets hurt em a little, let them know we mean business - if(world.time - co2overloadtime > 300) // They've been in here 30s now, lets start to kill them for their own good! + adjustOxyLoss(3) + + // They've been in here 30s now, lets start to kill them for their own good! + if(world.time - co2overloadtime > 300) adjustOxyLoss(8) - if(prob(20)) // Lets give them some chance to know somethings not right though I guess. + + // Lets give them some chance to know somethings not right though I guess. + if(prob(20)) spawn(0) emote("cough") else co2overloadtime = 0 - if(Toxins_pp > safe_toxins_max) // Too much toxins - var/ratio = (breath.toxins/safe_toxins_max) * 10 - //adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) //Limit amount of damage toxin exposure can do per second + // Too much poison in the air. + if(toxins_pp > safe_toxins_max) + var/ratio = (poison/safe_toxins_max) * 10 if(reagents) + //TODO: Fix Ravensdale's shit, make toxins toxins again instead of phoron. reagents.add_reagent("plasma", Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) toxins_alert = max(toxins_alert, 1) - else if(O2_pp > vox_oxygen_max && species.name == "Vox") //Oxygen is toxic to vox. - var/ratio = (breath.oxygen/vox_oxygen_max) * 1000 - adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) - toxins_alert = max(toxins_alert, 1) else toxins_alert = 0 - if(breath.trace_gases.len) // If there's some other shit in the air lets deal with it here. + // If there's some other shit in the air lets deal with it here. + if(breath.trace_gases.len) for(var/datum/gas/sleeping_agent/SA in breath.trace_gases) var/SA_pp = (SA.moles/breath.total_moles())*breath_pressure - if(SA_pp > SA_para_min) // Enough to make us paralysed for a bit - Paralyse(3) // 3 gives them one second to wake up and run away a bit! - if(SA_pp > SA_sleep_min) // Enough to make us sleep as well + + // Enough to make us paralysed for a bit + if(SA_pp > SA_para_min) + + // 3 gives them one second to wake up and run away a bit! + Paralyse(3) + + // Enough to make us sleep as well + if(SA_pp > SA_sleep_min) sleeping = min(sleeping+2, 10) - else if(SA_pp > 0.15) // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning + + // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning + else if(SA_pp > 0.15) if(prob(20)) spawn(0) emote(pick("giggle", "laugh")) SA.moles = 0 if( (abs(310.15 - breath.temperature) > 50) && !(COLD_RESISTANCE in mutations)) // Hot air hurts :( - if(status_flags & GODMODE) return 1 //godmode + + if(status_flags & GODMODE) + return 1 + if(breath.temperature < species.cold_level_1) if(prob(20)) src << "\red You feel your face freezing and an icicle forming in your lungs!" @@ -567,6 +626,11 @@ proc/handle_environment(datum/gas_mixture/environment) if(!environment) return + + //Moved pressure calculations here for use in skip-processing check. + var/pressure = environment.return_pressure() + var/adjusted_pressure = calculate_affecting_pressure(pressure) + if(!istype(get_turf(src), /turf/space)) //space is not meant to change your body temperature. var/loc_temp = T0C if(istype(loc, /obj/mecha)) @@ -578,7 +642,7 @@ else loc_temp = environment.temperature - if(abs(loc_temp - 293.15) < 20 && abs(bodytemperature - 310.14) < 0.5 && environment.toxins < MOLES_PLASMA_VISIBLE) + if(adjusted_pressure < species.warning_low_pressure && adjusted_pressure > species.warning_low_pressure && abs(loc_temp - 293.15) < 20 && abs(bodytemperature - 310.14) < 0.5 && environment.toxins < MOLES_PLASMA_VISIBLE) return // Temperatures are within normal ranges, fuck all this processing. ~Ccomp //Body temperature is adjusted in two steps. Firstly your body tries to stabilize itself a bit. @@ -630,9 +694,6 @@ // Account for massive pressure differences. Done by Polymorph // Made it possible to actually have something that can protect against high pressure... Done by Errorage. Polymorph now has an axe sticking from his head for his previous hardcoded nonsense! - - var/pressure = environment.return_pressure() - var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob. if(status_flags & GODMODE) return 1 //godmode if(adjusted_pressure >= species.hazard_high_pressure) @@ -1052,6 +1113,7 @@ if(halloss > 0) adjustHalLoss(-3) else if(sleeping) + speech_problem_flag = 1 handle_dreams() adjustHalLoss(-3) if (mind) @@ -1103,16 +1165,20 @@ //Other if(stunned) + speech_problem_flag = 1 AdjustStunned(-1) if(weakened) weakened = max(weakened-1,0) //before you get mad Rockdtben: I done this so update_canmove isn't called multiple times if(stuttering) + speech_problem_flag = 1 stuttering = max(stuttering-1, 0) if (slurring) + speech_problem_flag = 1 slurring = max(slurring-1, 0) if(silent) + speech_problem_flag = 1 silent = max(silent-1, 0) if(druggy) diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 8759cf41..7ec30fa3 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -1,50 +1,162 @@ /mob/living/carbon/human/say(var/message) + var/verb = "says" + var/alt_name = "" + var/message_range = world.view + var/italics = 0 - if(wear_mask) - if(istype(wear_mask, /obj/item/clothing/mask/gas/voice/space_ninja) && wear_mask:voice == "Unknown") - if(copytext(message, 1, 2) != "*") - var/list/temp_message = text2list(message, " ") - var/list/pick_list = list() - for(var/i = 1, i <= temp_message.len, i++) - pick_list += i - for(var/i=1, i <= abs(temp_message.len/3), i++) - var/H = pick(pick_list) - if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":")) continue - temp_message[H] = ninjaspeak(temp_message[H]) - pick_list -= H - message = list2text(temp_message, " ") - message = replacetext(message, "o", "¤") - message = replacetext(message, "p", "þ") - message = replacetext(message, "l", "£") - message = replacetext(message, "s", "§") - message = replacetext(message, "u", "µ") - message = replacetext(message, "b", "ß") + if(client) + if(client.prefs.muted & MUTE_IC) + src << "\red You cannot speak in IC (Muted)." + return - else if(istype(wear_mask, /obj/item/clothing/mask/horsehead)) - var/obj/item/clothing/mask/horsehead/hoers = wear_mask - if(hoers.voicechange) - if(!(copytext(message, 1, 2) == "*" || (mind && mind.changeling && department_radio_keys[copytext(message, 1, 3)] != "changeling"))) - message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!") + message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) -// if ((HULK in mutations) && health >= 25 && length(message)) -// if(copytext(message, 1, 2) != "*") -// message = "[uppertext(message)]!!" //because I don't know how to code properly in getting vars from other files -Bro + if(stat == 2) + return say_dead(message) - if (src.slurring) - if(copytext(message, 1, 2) != "*") - message = slur(message) - ..(message) + if (istype(wear_mask, /obj/item/clothing/mask/muzzle)) //Todo: Add this to speech_problem_flag checks. + return -/mob/living/carbon/human/say_understands(var/other,var/datum/language/speaking = null) + if(copytext(message,1,2) == "*") + return emote(copytext(message,2)) + + if(name != GetVoice()) + alt_name = "(as [get_id_name("Unknown")])" + + //parse the radio code and consume it + var/message_mode = parse_message_mode(message) + if (message_mode) + if (message_mode == "headset") + message = copytext(message,2) + else + message = copytext(message,3) + + //parse the language code and consume it + var/datum/language/speaking = parse_language(message) + if (speaking) + verb = speaking.speech_verb + message = copytext(message,3) + + message = capitalize(trim(message)) + + if(speech_problem_flag) + var/list/handle_r = handle_speech_problems(message) + message = handle_r[1] + verb = handle_r[2] + speech_problem_flag = handle_r[3] + + if(!message || stat) + return + + var/ending = copytext(message, length(message)) + if(ending=="!") + verb=pick("exclaims","shouts","yells") + if(ending=="?") + verb="asks" + + var/list/obj/item/used_radios = new + + switch (message_mode) + if("headset") + if(l_ear && istype(l_ear,/obj/item/device/radio)) + var/obj/item/device/radio/R = l_ear + R.talk_into(src,message,null,verb,speaking) + used_radios += l_ear + else if(r_ear && istype(r_ear,/obj/item/device/radio)) + var/obj/item/device/radio/R = r_ear + R.talk_into(src,message,null,verb,speaking) + used_radios += r_ear + + if("right ear") + var/obj/item/device/radio/R + var/has_radio = 0 + if(r_ear && istype(r_ear,/obj/item/device/radio)) + R = r_ear + has_radio = 1 + if(r_hand && istype(r_hand, /obj/item/device/radio)) + R = r_hand + has_radio = 1 + if(has_radio) + R.talk_into(src,message,null,verb,speaking) + used_radios += R + + + if("left ear") + var/obj/item/device/radio/R + var/has_radio = 0 + if(l_ear && istype(l_ear,/obj/item/device/radio)) + R = l_ear + has_radio = 1 + if(l_hand && istype(l_hand,/obj/item/device/radio)) + R = l_hand + has_radio = 1 + if(has_radio) + R.talk_into(src,message,null,verb,speaking) + used_radios += R + + if("intercom") + for(var/obj/item/device/radio/intercom/I in view(1, null)) + I.talk_into(src, message, verb, speaking) + used_radios += I + if("whisper") + whisper(message) + return + if("binary") + if(robot_talk_understand || binarycheck()) + robot_talk(message) + return + if("changeling") + if(mind && mind.changeling) + for(var/mob/Changeling in mob_list) + if((Changeling.mind && Changeling.mind.changeling) || istype(Changeling, /mob/dead/observer)) + Changeling << "[mind.changeling.changelingID]: [message]" + return + else + if(message_mode) + if(message_mode in (radiochannels | "department")) + if(l_ear && istype(l_ear,/obj/item/device/radio)) + l_ear.talk_into(src,message, message_mode, verb, speaking) + used_radios += l_ear + else if(r_ear && istype(r_ear,/obj/item/device/radio)) + r_ear.talk_into(src,message, message_mode, verb, speaking) + used_radios += r_ear + + + if(used_radios.len) + italics = 1 + message_range = 1 + + var/datum/gas_mixture/environment = loc.return_air() + if(environment) + var/pressure = environment.return_pressure() + if(pressure < SAY_MINIMUM_PRESSURE) + italics = 1 + message_range =1 + + if((species.name == "Vox" || species.name == "Vox Armalis") && prob(20)) + playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1) + + ..(message, speaking, verb, alt_name, italics, message_range, used_radios) + +/mob/living/carbon/human/say_understands(var/mob/other,var/datum/language/speaking = null) if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak. return 1 + if (istype(other, /mob/living/carbon/monkey/diona) && !speaking) + if(other.languages.len >= 2) //They've sucked down some blood and can speak common now. + return 1 + if (istype(other, /mob/living/silicon)) return 1 if (istype(other, /mob/living/carbon/brain)) return 1 if (istype(other, /mob/living/carbon/slime)) return 1 + if (istype(other, /mob/living/simple_animal)) + if(other.universal_speak || src.universal_speak || src.universal_understand) + return 1 + return 0 + return ..() /mob/living/carbon/human/GetVoice() @@ -71,3 +183,47 @@ /mob/living/carbon/human/proc/GetSpecialVoice() return special_voice + +/mob/living/carbon/human/proc/handle_speech_problems(var/message) + var/list/returns[3] + var/verb = "says" + var/handled = 0 + if(silent) + message = "" + handled = 1 + if(sdisabilities & MUTE) + message = "" + handled = 1 + if(wear_mask) + if(istype(wear_mask, /obj/item/clothing/mask/horsehead)) + var/obj/item/clothing/mask/horsehead/hoers = wear_mask + if(hoers.voicechange) + if(mind && mind.changeling && department_radio_keys[copytext(message, 1, 3)] != "changeling") + message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!") + verb = pick("whinnies","neighs", "says") + handled = 1 + + if((HULK in mutations) && health >= 25 && length(message)) + message = "[uppertext(message)]!!!" + verb = pick("yells","roars","hollers") + handled = 1 + if(slurring) + message = slur(message) + verb = pick("stammers","stutters") + handled = 1 + + var/braindam = getBrainLoss() + if(braindam >= 60) + handled = 1 + if(prob(braindam/4)) + message = stutter(message) + verb = pick("stammers", "stutters") + if(prob(braindam)) + message = uppertext(message) + verb = pick("yells like an idiot","says rather loudly") + + returns[1] = message + returns[2] = verb + returns[3] = handled + + return returns diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 6197ab64..35af50be 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1,3 +1,11 @@ +/* + Global associative list for caching humanoid icons. + Index format m or f, followed by a string of 0 and 1 to represent bodyparts followed by husk fat hulk skeleton 1 or 0. + TODO: Proper documentation + icon_key is [species.race_key][g][husk][fat][hulk][skeleton][s_tone] +*/ +var/global/list/human_icon_cache = list() + /////////////////////// //UPDATE_ICONS SYSTEM// /////////////////////// @@ -97,26 +105,26 @@ Please contact me on #coderbus IRC. ~Carn x */ //Human Overlays Indexes///////// -#define MUTANTRACE_LAYER 1 //TODO: make part of body? +#define MUTANTRACE_LAYER 1 #define MUTATIONS_LAYER 2 #define DAMAGE_LAYER 3 #define UNIFORM_LAYER 4 -#define ID_LAYER 5 -#define SHOES_LAYER 6 -#define GLOVES_LAYER 7 -#define EARS_LAYER 8 -#define SUIT_LAYER 9 -#define GLASSES_LAYER 10 -#define BELT_LAYER 11 //Possible make this an overlay of somethign required to wear a belt? -#define SUIT_STORE_LAYER 12 -#define BACK_LAYER 13 -#define HAIR_LAYER 14 //TODO: make part of head layer? -#define FACEMASK_LAYER 15 -#define HEAD_LAYER 16 -#define COLLAR_LAYER 17 -#define HANDCUFF_LAYER 18 -#define LEGCUFF_LAYER 19 -#define TAIL_LAYER 20 //bs12 specific. this hack is probably gonna come back to haunt me +#define TAIL_LAYER 5 //bs12 specific. this hack is probably gonna come back to haunt me +#define ID_LAYER 6 +#define SHOES_LAYER 7 +#define GLOVES_LAYER 8 +#define EARS_LAYER 9 +#define SUIT_LAYER 10 +#define GLASSES_LAYER 11 +#define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt? +#define SUIT_STORE_LAYER 13 +#define BACK_LAYER 14 +#define HAIR_LAYER 15 //TODO: make part of head layer? +#define FACEMASK_LAYER 16 +#define HEAD_LAYER 17 +#define COLLAR_LAYER 18 +#define HANDCUFF_LAYER 19 +#define LEGCUFF_LAYER 20 #define L_HAND_LAYER 21 #define R_HAND_LAYER 22 #define TARGETED_LAYER 23 //BS12: Layer for the target overlay from weapon targeting system @@ -195,7 +203,6 @@ proc/get_damage_icon_part(damage_state, body_part) var/image/standing_image = new /image("icon" = standing) - // blend the individual damage states with our icons for(var/datum/organ/external/O in organs) if(!(O.status & ORGAN_DESTROYED)) @@ -206,44 +213,75 @@ proc/get_damage_icon_part(damage_state, body_part) standing_image.overlays += DI - overlays_standing[DAMAGE_LAYER] = standing_image if(update_icons) update_icons() //BASE MOB SPRITE /mob/living/carbon/human/proc/update_body(var/update_icons=1) - if(stand_icon) del(stand_icon) var/husk_color_mod = rgb(96,88,80) var/hulk_color_mod = rgb(48,224,40) var/necrosis_color_mod = rgb(10,50,0) - var/husk = (HUSK in src.mutations) //100% unnecessary -Agouri //nope, do you really want to iterate through src.mutations repeatedly? -Pete + var/husk = (HUSK in src.mutations) var/fat = (FAT in src.mutations) var/hulk = (HULK in src.mutations) var/skeleton = (SKELETON in src.mutations) - var/g = "m" - if(gender == FEMALE) g = "f" - - var/datum/organ/external/chest = get_organ("chest") - stand_icon = chest.get_icon(g) - if(!skeleton) - if(husk) - stand_icon.ColorTone(husk_color_mod) - else if(hulk) - var/list/TONE = ReadRGB(hulk_color_mod) - stand_icon.MapColors(rgb(TONE[1],0,0),rgb(0,TONE[2],0),rgb(0,0,TONE[3])) - - var/datum/organ/external/head = get_organ("head") + var/g = (gender == FEMALE ? "f" : "m") var/has_head = 0 - if(head && !(head.status & ORGAN_DESTROYED)) - has_head = 1 + //CACHING: Generate an index key from visible bodyparts. + //0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic. + + //Create a new, blank icon for our mob to use. + if(stand_icon) + del(stand_icon) + + stand_icon = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi',"blank") + + var/icon_key = "[species.race_key][g][s_tone]" for(var/datum/organ/external/part in organs) - if(!istype(part, /datum/organ/external/chest) && !(part.status & ORGAN_DESTROYED)) - var/icon/temp + + if(istype(part,/datum/organ/external/head) && !(part.status & ORGAN_DESTROYED)) + has_head = 1 + + if(part.status & ORGAN_DESTROYED) + icon_key = "[icon_key]0" + else if(part.status & ORGAN_ROBOT) + icon_key = "[icon_key]2" + else if(part.status & ORGAN_DEAD) //Do we even have necrosis in our current code? ~Z + icon_key = "[icon_key]3" + else + icon_key = "[icon_key]1" + + icon_key = "[icon_key][husk ? 1 : 0][fat ? 1 : 0][hulk ? 1 : 0][skeleton ? 1 : 0][s_tone]" + + var/icon/base_icon + if(human_icon_cache[icon_key]) + //Icon is cached, use existing icon. + base_icon = human_icon_cache[icon_key] + + //log_debug("Retrieved cached mob icon ([icon_key] \icon[human_icon_cache[icon_key]]) for [src].") + + else + + //BEGIN CACHED ICON GENERATION. + + //Icon is not cached, generate and store it. + //Robotic limbs are handled in get_icon() so all we worry about are missing or dead limbs. + //No icon stored, so we need to start with a basic one. + var/datum/organ/external/chest = get_organ("chest") + base_icon = chest.get_icon(g) + + for(var/datum/organ/external/part in organs) + + var/icon/temp //Hold the bodypart icon for processing. + + if(part.status & ORGAN_DESTROYED) + continue + if (istype(part, /datum/organ/external/groin) || istype(part, /datum/organ/external/head)) temp = part.get_icon(g) else @@ -253,46 +291,70 @@ proc/get_damage_icon_part(damage_state, body_part) temp.ColorTone(necrosis_color_mod) temp.SetIntensity(0.7) - else if(!skeleton) - if(husk) - temp.ColorTone(husk_color_mod) - else if(hulk) - var/list/TONE = ReadRGB(hulk_color_mod) - temp.MapColors(rgb(TONE[1],0,0),rgb(0,TONE[2],0),rgb(0,0,TONE[3])) - //That part makes left and right legs drawn topmost and lowermost when human looks WEST or EAST //And no change in rendering for other parts (they icon_position is 0, so goes to 'else' part) if(part.icon_position&(LEFT|RIGHT)) + var/icon/temp2 = new('icons/mob/human.dmi',"blank") + temp2.Insert(new/icon(temp,dir=NORTH),dir=NORTH) temp2.Insert(new/icon(temp,dir=SOUTH),dir=SOUTH) + if(!(part.icon_position & LEFT)) temp2.Insert(new/icon(temp,dir=EAST),dir=EAST) + if(!(part.icon_position & RIGHT)) temp2.Insert(new/icon(temp,dir=WEST),dir=WEST) - stand_icon.Blend(temp2, ICON_OVERLAY) - temp2 = new('icons/mob/human.dmi',"blank") + + base_icon.Blend(temp2, ICON_OVERLAY) + if(part.icon_position & LEFT) temp2.Insert(new/icon(temp,dir=EAST),dir=EAST) + if(part.icon_position & RIGHT) temp2.Insert(new/icon(temp,dir=WEST),dir=WEST) - stand_icon.Blend(temp2, ICON_UNDERLAY) + + base_icon.Blend(temp2, ICON_UNDERLAY) + else - stand_icon.Blend(temp, ICON_OVERLAY) - //Skin tone - if(!skeleton && !husk && !hulk && (species.flags & HAS_SKIN_TONE)) - if(s_tone >= 0) - stand_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) - else - stand_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) + base_icon.Blend(temp, ICON_OVERLAY) - if(husk) - var/icon/mask = new(stand_icon) - var/icon/husk_over = new(race_icon,"overlay_husk") - mask.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0) - husk_over.Blend(mask, ICON_ADD) - stand_icon.Blend(husk_over, ICON_OVERLAY) + if(!skeleton) + if(husk) + base_icon.ColorTone(husk_color_mod) + else if(hulk) + var/list/tone = ReadRGB(hulk_color_mod) + base_icon.MapColors(rgb(tone[1],0,0),rgb(0,tone[2],0),rgb(0,0,tone[3])) + + //Handle husk overlay. + if(husk) + var/icon/mask = new(base_icon) + var/icon/husk_over = new(race_icon,"overlay_husk") + mask.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0) + husk_over.Blend(mask, ICON_ADD) + base_icon.Blend(husk_over, ICON_OVERLAY) + + + //Skin tone. + if(!husk && !hulk) + if(species.flags & HAS_SKIN_TONE) + if(s_tone >= 0) + base_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) + else + base_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) + + human_icon_cache[icon_key] = base_icon + + //log_debug("Generated new cached mob icon ([icon_key] \icon[human_icon_cache[icon_key]]) for [src]. [human_icon_cache.len] cached mob icons.") + + //END CACHED ICON GENERATION. + + stand_icon.Blend(base_icon,ICON_OVERLAY) + + //Skin colour. Not in cache because highly variable (and relatively benign). + if (species.flags & HAS_SKIN_COLOR) + stand_icon.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) if(has_head) //Eyes @@ -310,6 +372,9 @@ proc/get_damage_icon_part(damage_state, body_part) if(!fat && !skeleton) stand_icon.Blend(new /icon('icons/mob/human.dmi', "underwear[underwear]_[g]_s"), ICON_OVERLAY) + if(undershirt>0 && undershirt < 5 && species.flags & HAS_UNDERWEAR) + stand_icon.Blend(new /icon('icons/mob/human.dmi', "undershirt[undershirt]_s"), ICON_OVERLAY) + if(update_icons) update_icons() @@ -317,6 +382,8 @@ proc/get_damage_icon_part(damage_state, body_part) update_tail_showing(0) + + //HAIR OVERLAY /mob/living/carbon/human/proc/update_hair(var/update_icons=1) //Reset our hair @@ -479,7 +546,7 @@ proc/get_damage_icon_part(damage_state, body_part) if(!t_color) t_color = icon_state var/image/standing = image("icon_state" = "[t_color]_s") - standing.icon = ((w_uniform.icon_override) ? w_uniform.icon_override : 'icons/mob/uniform.dmi') + standing.icon = ((w_uniform.icon_override) ? w_uniform.icon_override : (species.sprite_sheets["uniform"] ? species.sprite_sheets["uniform"] : 'icons/mob/uniform.dmi')) if(w_uniform.blood_DNA) var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "uniformblood") @@ -494,6 +561,7 @@ proc/get_damage_icon_part(damage_state, body_part) overlays_standing[UNIFORM_LAYER] = standing else overlays_standing[UNIFORM_LAYER] = null + // This really, really seems like it should not be mixed in the middle of display code... // Automatically drop anything in store / id / belt if you're not wearing a uniform. //CHECK IF NECESARRY for( var/obj/item/thing in list(r_store, l_store, wear_id, belt) ) // if(thing) // @@ -526,7 +594,7 @@ proc/get_damage_icon_part(damage_state, body_part) if(gloves) var/t_state = gloves.item_state if(!t_state) t_state = gloves.icon_state - var/image/standing = image("icon" = ((gloves.icon_override) ? gloves.icon_override : 'icons/mob/hands.dmi'), "icon_state" = "[t_state]") + var/image/standing = image("icon" = ((gloves.icon_override) ? gloves.icon_override : (species.sprite_sheets["gloves"] ? species.sprite_sheets["gloves"] : 'icons/mob/hands.dmi')), "icon_state" = "[t_state]") if(gloves.blood_DNA) var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "bloodyhands") bloodsies.color = gloves.blood_color @@ -545,7 +613,7 @@ proc/get_damage_icon_part(damage_state, body_part) /mob/living/carbon/human/update_inv_glasses(var/update_icons=1) if(glasses) - overlays_standing[GLASSES_LAYER] = image("icon" = ((glasses.icon_override) ? glasses.icon_override : 'icons/mob/eyes.dmi'), "icon_state" = "[glasses.icon_state]") + overlays_standing[GLASSES_LAYER] = image("icon" = ((glasses.icon_override) ? glasses.icon_override : (species.sprite_sheets["eyes"] ? species.sprite_sheets["eyes"] : 'icons/mob/eyes.dmi')), "icon_state" = "[glasses.icon_state]") else overlays_standing[GLASSES_LAYER] = null if(update_icons) update_icons() @@ -553,16 +621,20 @@ proc/get_damage_icon_part(damage_state, body_part) /mob/living/carbon/human/update_inv_ears(var/update_icons=1) if(l_ear || r_ear) if(l_ear) - overlays_standing[EARS_LAYER] = image("icon" = ((l_ear.icon_override) ? l_ear.icon_override : 'icons/mob/ears.dmi'), "icon_state" = "[l_ear.icon_state]") + var/t_type = l_ear.icon_state + if(l_ear.icon_override || species.sprite_sheets["ears"]) t_type = "[t_type]_l" + overlays_standing[EARS_LAYER] = image("icon" = ((l_ear.icon_override) ? l_ear.icon_override : (species.sprite_sheets["ears"] ? species.sprite_sheets["ears"] : 'icons/mob/ears.dmi')), "icon_state" = "[t_type]") if(r_ear) - overlays_standing[EARS_LAYER] = image("icon" = ((r_ear.icon_override) ? r_ear.icon_override : 'icons/mob/ears.dmi'), "icon_state" = "[r_ear.icon_state]") + var/t_type = r_ear.icon_state + if(r_ear.icon_override || species.sprite_sheets["ears"]) t_type = "[t_type]_r" + overlays_standing[EARS_LAYER] = image("icon" = ((r_ear.icon_override) ? r_ear.icon_override : (species.sprite_sheets["ears"] ? species.sprite_sheets["ears"] : 'icons/mob/ears.dmi')), "icon_state" = "t_type]") else overlays_standing[EARS_LAYER] = null if(update_icons) update_icons() /mob/living/carbon/human/update_inv_shoes(var/update_icons=1) if(shoes) - var/image/standing = image("icon" = ((shoes.icon_override) ? shoes.icon_override : 'icons/mob/feet.dmi'), "icon_state" = "[shoes.icon_state]") + var/image/standing = image("icon" = ((shoes.icon_override) ? shoes.icon_override : (species.sprite_sheets["feet"] ? species.sprite_sheets["feet"] : 'icons/mob/feet.dmi')), "icon_state" = "[shoes.icon_state]") if(shoes.blood_DNA) var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "shoeblood") bloodsies.color = shoes.blood_color @@ -595,7 +667,7 @@ proc/get_damage_icon_part(damage_state, body_part) if(istype(head,/obj/item/clothing/head/kitty)) standing = image("icon" = head:mob) else - standing = image("icon" = ((head.icon_override) ? head.icon_override : 'icons/mob/head.dmi'), "icon_state" = "[head.icon_state]") + standing = image("icon" = ((head.icon_override) ? head.icon_override : (species.sprite_sheets["head"] ? species.sprite_sheets["head"] : 'icons/mob/head.dmi')), "icon_state" = "[head.icon_state]") if(head.blood_DNA) var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood") bloodsies.color = head.blood_color @@ -610,7 +682,7 @@ proc/get_damage_icon_part(damage_state, body_part) belt.screen_loc = ui_belt //TODO var/t_state = belt.item_state if(!t_state) t_state = belt.icon_state - overlays_standing[BELT_LAYER] = image("icon" = ((belt.icon_override) ? belt.icon_override : 'icons/mob/belt.dmi'), "icon_state" = "[t_state]") + overlays_standing[BELT_LAYER] = image("icon" = ((belt.icon_override) ? belt.icon_override : (species.sprite_sheets["belt"] ? species.sprite_sheets["belt"] : 'icons/mob/belt.dmi')), "icon_state" = "[t_state]") else overlays_standing[BELT_LAYER] = null if(update_icons) update_icons() @@ -619,7 +691,7 @@ proc/get_damage_icon_part(damage_state, body_part) /mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1) if( wear_suit && istype(wear_suit, /obj/item/clothing/suit) ) //TODO check this wear_suit.screen_loc = ui_oclothing //TODO - var/image/standing = image("icon" = ((wear_suit.icon_override) ? wear_suit.icon_override : 'icons/mob/suit.dmi'), "icon_state" = "[wear_suit.icon_state]") + var/image/standing = image("icon" = ((wear_suit.icon_override) ? wear_suit.icon_override : (species.sprite_sheets["suit"] ? species.sprite_sheets["suit"] : 'icons/mob/suit.dmi')), "icon_state" = "[wear_suit.icon_state]") if( istype(wear_suit, /obj/item/clothing/suit/straight_jacket) ) drop_from_inventory(handcuffed) @@ -654,7 +726,7 @@ proc/get_damage_icon_part(damage_state, body_part) /mob/living/carbon/human/update_inv_wear_mask(var/update_icons=1) if( wear_mask && ( istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/tie) ) ) wear_mask.screen_loc = ui_mask //TODO - var/image/standing = image("icon" = ((wear_mask.icon_override) ? wear_mask.icon_override : 'icons/mob/mask.dmi'), "icon_state" = "[wear_mask.icon_state]") + var/image/standing = image("icon" = ((wear_mask.icon_override) ? wear_mask.icon_override : (species.sprite_sheets["mask"] ? species.sprite_sheets["mask"] : 'icons/mob/mask.dmi')), "icon_state" = "[wear_mask.icon_state]") if( !istype(wear_mask, /obj/item/clothing/mask/cigarette) && wear_mask.blood_DNA ) var/image/bloodsies = image("icon" = 'icons/effects/blood.dmi', "icon_state" = "maskblood") bloodsies.color = wear_mask.blood_color @@ -668,7 +740,7 @@ proc/get_damage_icon_part(damage_state, body_part) /mob/living/carbon/human/update_inv_back(var/update_icons=1) if(back) back.screen_loc = ui_back //TODO - overlays_standing[BACK_LAYER] = image("icon" = ((back.icon_override) ? back.icon_override : 'icons/mob/back.dmi'), "icon_state" = "[back.icon_state]") + overlays_standing[BACK_LAYER] = image("icon" = ((back.icon_override) ? back.icon_override : (species.sprite_sheets["back"] ? species.sprite_sheets["back"] : 'icons/mob/back.dmi')), "icon_state" = "[back.icon_state]") else overlays_standing[BACK_LAYER] = null if(update_icons) update_icons() @@ -709,7 +781,8 @@ proc/get_damage_icon_part(damage_state, body_part) r_hand.screen_loc = ui_rhand //TODO var/t_state = r_hand.item_state if(!t_state) t_state = r_hand.icon_state - overlays_standing[R_HAND_LAYER] = image("icon" = 'icons/mob/items_righthand.dmi', "icon_state" = "[t_state]") + if(r_hand.icon_override || species.sprite_sheets["held"]) t_state = "[t_state]_r" + overlays_standing[R_HAND_LAYER] = image("icon" = ((r_hand.icon_override) ? r_hand.icon_override : (species.sprite_sheets["held"] ? species.sprite_sheets["held"] : 'icons/mob/items_righthand.dmi')), "icon_state" = "[t_state]") if (handcuffed) drop_r_hand() else overlays_standing[R_HAND_LAYER] = null @@ -721,7 +794,8 @@ proc/get_damage_icon_part(damage_state, body_part) l_hand.screen_loc = ui_lhand //TODO var/t_state = l_hand.item_state if(!t_state) t_state = l_hand.icon_state - overlays_standing[L_HAND_LAYER] = image("icon" = 'icons/mob/items_lefthand.dmi', "icon_state" = "[t_state]") + if(l_hand.icon_override || species.sprite_sheets["held"]) t_state = "[t_state]_l" + overlays_standing[L_HAND_LAYER] = image("icon" = ((l_hand.icon_override) ? l_hand.icon_override : (species.sprite_sheets["held"] ? species.sprite_sheets["held"] : 'icons/mob/items_lefthand.dmi')), "icon_state" = "[t_state]") if (handcuffed) drop_l_hand() else overlays_standing[L_HAND_LAYER] = null @@ -731,8 +805,11 @@ proc/get_damage_icon_part(damage_state, body_part) overlays_standing[TAIL_LAYER] = null if(species.tail && species.flags & HAS_TAIL) - if(!wear_suit || !(wear_suit.flags_inv & HIDEJUMPSUIT) && !istype(wear_suit, /obj/item/clothing/suit/space)) - overlays_standing[TAIL_LAYER] = image("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s") + if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space)) + var/icon/tail_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s") + tail_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD) + + overlays_standing[TAIL_LAYER] = image(tail_s) if(update_icons) update_icons() @@ -793,6 +870,7 @@ proc/get_damage_icon_part(damage_state, body_part) #undef MUTATIONS_LAYER #undef DAMAGE_LAYER #undef UNIFORM_LAYER +#undef TAIL_LAYER #undef ID_LAYER #undef SHOES_LAYER #undef GLOVES_LAYER @@ -810,6 +888,5 @@ proc/get_damage_icon_part(damage_state, body_part) #undef LEGCUFF_LAYER #undef L_HAND_LAYER #undef R_HAND_LAYER -#undef TAIL_LAYER #undef TARGETED_LAYER #undef TOTAL_LAYERS diff --git a/code/modules/mob/living/carbon/monkey/diona.dm b/code/modules/mob/living/carbon/monkey/diona.dm index eb8dedb4..cf1ea1cc 100644 --- a/code/modules/mob/living/carbon/monkey/diona.dm +++ b/code/modules/mob/living/carbon/monkey/diona.dm @@ -2,45 +2,6 @@ Tiny babby plant critter plus procs. */ -//Helper object for picking dionaea (and other creatures) up. -/obj/item/weapon/holder - name = "holder" - desc = "You shouldn't ever see this." - -/obj/item/weapon/holder/diona - - name = "diona nymph" - desc = "It's a tiny plant critter." - icon = 'icons/obj/objects.dmi' - icon_state = "nymph" - slot_flags = SLOT_HEAD - origin_tech = "magnets=3;biotech=5" - -/obj/item/weapon/holder/New() - ..() - processing_objects.Add(src) - -/obj/item/weapon/holder/Del() - //Hopefully this will stop the icon from remaining on human mobs. - if(istype(loc,/mob/living)) - var/mob/living/A = src.loc - src.loc = null - A.update_icons() - processing_objects.Remove(src) - ..() - -/obj/item/weapon/holder/process() - if(!loc) del(src) - - if(istype(loc,/turf) || !(contents.len)) - for(var/mob/M in contents) - M.loc = get_turf(src) - del(src) - -/obj/item/weapon/holder/attackby(obj/item/weapon/W as obj, mob/user as mob) - for(var/mob/M in src.contents) - M.attackby(W,user) - //Mob defines. /mob/living/carbon/monkey/diona name = "diona nymph" @@ -67,6 +28,7 @@ D.attack_hand(M) M << "You scoop up [src]." src << "[M] scoops you up." + M.status_flags |= PASSEMOTES return ..() @@ -108,6 +70,8 @@ if(istype(M,/mob/living/carbon/human)) M << "You feel your being twine with that of [src] as it merges with your biomass." + M.status_flags |= PASSEMOTES + src << "You feel your being twine with that of [M] as you merge with its biomass." src.loc = M src.verbs += /mob/living/carbon/monkey/diona/proc/split @@ -127,10 +91,19 @@ src.loc << "You feel a pang of loss as [src] splits away from your biomass." src << "You wiggle out of the depths of [src.loc]'s biomass and plop to the ground." + + var/mob/living/M = src.loc + src.loc = get_turf(src) src.verbs -= /mob/living/carbon/monkey/diona/proc/split src.verbs += /mob/living/carbon/monkey/diona/proc/merge + if(istype(M)) + for(var/atom/A in M.contents) + if(istype(A,/mob/living/simple_animal/borer) || istype(A,/obj/item/weapon/holder)) + return + M.status_flags &= ~PASSEMOTES + /mob/living/carbon/monkey/diona/verb/fertilize_plant() set category = "Diona" @@ -188,7 +161,7 @@ return src.split() - src.visible_message("\red [src] begins to shift and quiver, and erupts in a shower of shed bark and twigs!","\red You begin to shift and quiver, then erupt in a shower of shed bark and twigs, attaining your adult form!") + src.visible_message("\red [src] begins to shift and quiver, and erupts in a shower of shed bark as it splits into a tangle of nearly a dozen new dionaea.","\red You begin to shift and quiver, feeling your awareness splinter. All at once, we consume our stored nutrients to surge with growth, splitting into a tangle of at least a dozen new dionaea. We have attained our gestalt form.") var/mob/living/carbon/human/adult = new(get_turf(src.loc)) adult.set_species("Diona") @@ -252,3 +225,51 @@ src << "\green You feel your awareness expand, and realize you know how to understand the creatures around you." else src << "\green The blood seeps into your small form, and you draw out the echoes of memories and personality from it, working them into your budding mind." + + +/mob/living/carbon/monkey/diona/say_understands(var/mob/other,var/datum/language/speaking = null) + + if (istype(other, /mob/living/carbon/human) && !speaking) + if(languages.len >= 2) // They have sucked down some blood. + return 1 + return ..() + +/mob/living/carbon/monkey/diona/say(var/message) + var/verb = "says" + var/message_range = world.view + + if(client) + if(client.prefs.muted & MUTE_IC) + src << "\red You cannot speak in IC (Muted)." + return + + message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) + + + if(stat == 2) + return say_dead(message) + + var/datum/language/speaking = null + + + + if(length(message) >= 2) + var/channel_prefix = copytext(message, 1 ,3) + if(languages.len) + for(var/datum/language/L in languages) + if(lowertext(channel_prefix) == ":[L.key]") + verb = L.speech_verb + speaking = L + break + + if(speaking) + message = trim(copytext(message,3)) + + message = capitalize(trim_left(message)) + + if(!message || stat) + return + + + + ..(message, speaking, verb, null, null, message_range, null) diff --git a/code/modules/mob/living/carbon/monkey/emote.dm b/code/modules/mob/living/carbon/monkey/emote.dm index 8c8c54f5..21057a0b 100644 --- a/code/modules/mob/living/carbon/monkey/emote.dm +++ b/code/modules/mob/living/carbon/monkey/emote.dm @@ -31,6 +31,11 @@ if ("custom") return custom_emote(m_type, message) + if ("chirp") + if(istype(src,/mob/living/carbon/monkey/diona)) + message = "The [src.name] chirps!" + playsound(src.loc, 'sound/misc/nymphchirp.ogg', 50, 0) + m_type = 2 if("sign") if (!src.restrained()) message = text("The monkey signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) @@ -114,7 +119,11 @@ message = "The [src.name] lets out a faint chimper as it collapses and stops moving..." m_type = 1 if("help") - src << "choke, collapse, dance, deathgasp, drool, gasp, shiver, gnarl, jump, paw, moan, nod, roar, roll, scratch,\nscretch, shake, sign-#, sit, sulk, sway, tail, twitch, whimper" + var/text = "choke, " + if(istype(src,/mob/living/carbon/monkey/diona)) + text += "chirp, " + text += "collapse, dance, deathgasp, drool, gasp, shiver, gnarl, jump, paw, moan, nod, roar, roll, scratch,\nscretch, shake, sign-#, sit, sulk, sway, tail, twitch, whimper" + src << text else src << text("Invalid Emote: []", act) if ((message && src.stat == 0)) diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index 0bcbaf30..eefd3bad 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -22,7 +22,7 @@ if(loc) environment = loc.return_air() - if (stat != DEAD) + if (stat != DEAD) if(!istype(src,/mob/living/carbon/monkey/diona)) //still breathing //First, resolve location and get a breath if(air_master.current_cycle%4==2) @@ -79,7 +79,7 @@ if(prob(1)) emote(pick("scratch","jump","roll","tail")) updatehealth() - + /mob/living/carbon/monkey/calculate_affecting_pressure(var/pressure) ..() @@ -174,9 +174,9 @@ for (var/ID in virus2) var/datum/disease2/disease/V = virus2[ID] V.cure(src) - + for(var/obj/effect/decal/cleanable/O in view(1,src)) - if(istype(O,/obj/effect/decal/cleanable/blood)) + if(istype(O,/obj/effect/decal/cleanable/blood)) var/obj/effect/decal/cleanable/blood/B = O if(B.virus2.len) for (var/ID in B.virus2) @@ -397,9 +397,18 @@ if(!environment) return - if(abs(environment.temperature - 293.15) < 20 && abs(bodytemperature - 310.14) < 0.5 && environment.toxins < MOLES_PLASMA_VISIBLE) - return // Temperatures are within normal ranges, fuck all this processing. ~Ccomp - + //Moved these vars here for use in the fuck-it-skip-processing check. + var/pressure = environment.return_pressure() + var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob. + + if(adjusted_pressure < WARNING_HIGH_PRESSURE && adjusted_pressure > WARNING_LOW_PRESSURE && abs(environment.temperature - 293.15) < 20 && abs(bodytemperature - 310.14) < 0.5 && environment.toxins < MOLES_PLASMA_VISIBLE) + + //Hopefully should fix the walk-inside-still-pressure-warning issue. + if(pressure_alert) + pressure_alert = 0 + + return // Temperatures are within normal ranges, fuck all this processing. ~Ccomp + var/environment_heat_capacity = environment.heat_capacity() if(istype(get_turf(src), /turf/space)) var/turf/heat_turf = get_turf(src) @@ -414,9 +423,6 @@ bodytemperature += 0.1*(environment.temperature - bodytemperature)*environment_heat_capacity/(environment_heat_capacity + 270000) //Account for massive pressure differences - - var/pressure = environment.return_pressure() - var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob. switch(adjusted_pressure) if(HAZARD_HIGH_PRESSURE to INFINITY) adjustBruteLoss( min( ( (adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) ) @@ -468,7 +474,7 @@ adjustToxLoss(-1) adjustOxyLoss(-1) - if(reagents && reagents.reagent_list.len) + if(reagents && reagents.reagent_list.len) reagents.metabolize(src,alien) if (drowsyness) diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index feefff2b..3011b565 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -513,7 +513,21 @@ /mob/living/carbon/monkey/IsAdvancedToolUser()//Unless its monkey mode monkeys cant use advanced tools - if(!ticker) return 0 - if(!ticker.mode.name == "monkey") return 0 - return 1 + return 0 +/mob/living/carbon/monkey/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/italics=0, var/message_range = world.view, var/list/used_radios = list()) + if(stat) + return + + if(copytext(message,1,2) == "*") + return emote(copytext(message,2)) + + if(stat) + return + + if(speak_emote.len) + verb = pick(speak_emote) + + message = capitalize(trim_left(message)) + + ..(message, speaking, verb, alt_name, italics, message_range, used_radios) diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm index 384774f1..f24171d9 100644 --- a/code/modules/mob/living/carbon/species.dm +++ b/code/modules/mob/living/carbon/species.dm @@ -17,6 +17,8 @@ var/mutantrace // Safeguard due to old code. var/breath_type = "oxygen" // Non-oxygen gas breathed, if any. + var/poison_type = "plasma" // Poisonous air. + var/exhale_type = "C02" // Exhaled gas type. var/cold_level_1 = 260 // Cold damage level 1 below this point. var/cold_level_2 = 200 // Cold damage level 2 below this point. @@ -42,19 +44,72 @@ var/blood_color = "#A10808" //Red. var/flesh_color = "#FFC896" //Pink. -/datum/species/proc/handle_post_spawn(var/mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment. + //Used in icon caching. + var/race_key = 0 + var/icon/icon_template + + /* Species-specific sprites, concept stolen from Paradise//vg/. + ex: + sprite_sheets = list( + "held" = 'icons/mob/path', + "uniform" = 'icons/mob/path', + "suit" = 'icons/mob/path', + "belt" = 'icons/mob/path' + "head" = 'icons/mob/path', + "back" = 'icons/mob/path', + "mask" = 'icons/mob/path', + "ears" = 'icons/mob/path', + "eyes" = 'icons/mob/path', + "feet" = 'icons/mob/path', + "gloves" = 'icons/mob/path' + ) + If index term exists and icon_override is not set, this sprite sheet will be used. + */ + + var/list/sprite_sheets = list() + +/datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs. + //This is a basic humanoid limb setup. + H.organs = list() + H.organs_by_name["chest"] = new/datum/organ/external/chest() + H.organs_by_name["groin"] = new/datum/organ/external/groin(H.organs_by_name["chest"]) + H.organs_by_name["head"] = new/datum/organ/external/head(H.organs_by_name["chest"]) + H.organs_by_name["l_arm"] = new/datum/organ/external/l_arm(H.organs_by_name["chest"]) + H.organs_by_name["r_arm"] = new/datum/organ/external/r_arm(H.organs_by_name["chest"]) + H.organs_by_name["r_leg"] = new/datum/organ/external/r_leg(H.organs_by_name["groin"]) + H.organs_by_name["l_leg"] = new/datum/organ/external/l_leg(H.organs_by_name["groin"]) + H.organs_by_name["l_hand"] = new/datum/organ/external/l_hand(H.organs_by_name["l_arm"]) + H.organs_by_name["r_hand"] = new/datum/organ/external/r_hand(H.organs_by_name["r_arm"]) + H.organs_by_name["l_foot"] = new/datum/organ/external/l_foot(H.organs_by_name["l_leg"]) + H.organs_by_name["r_foot"] = new/datum/organ/external/r_foot(H.organs_by_name["r_leg"]) + + H.internal_organs = list() + H.internal_organs_by_name["heart"] = new/datum/organ/internal/heart(H) + H.internal_organs_by_name["lungs"] = new/datum/organ/internal/lungs(H) + H.internal_organs_by_name["liver"] = new/datum/organ/internal/liver(H) + H.internal_organs_by_name["kidney"] = new/datum/organ/internal/kidney(H) + H.internal_organs_by_name["brain"] = new/datum/organ/internal/brain(H) + H.internal_organs_by_name["eyes"] = new/datum/organ/internal/eyes(H) + + for(var/name in H.organs_by_name) + H.organs += H.organs_by_name[name] + + for(var/datum/organ/external/O in H.organs) + O.owner = H if(flags & IS_SYNTHETIC) for(var/datum/organ/external/E in H.organs) if(E.status & ORGAN_CUT_AWAY || E.status & ORGAN_DESTROYED) continue E.status |= ORGAN_ROBOT for(var/datum/organ/internal/I in H.internal_organs) - I.robotic = 2 + I.mechanize() + +/datum/species/proc/handle_post_spawn(var/mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment. return /datum/species/proc/handle_death(var/mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns). if(flags & IS_SYNTHETIC) - //H.make_jittery(200) //S-s-s-s-sytem f-f-ai-i-i-i-i-lure-ure-ure-ure + //H.make_jittery(200) //S-s-s-s-sytem f-f-ai-i-i-i-i-lure-ure-ure-ure H.h_style = "" spawn(100) //H.is_jittery = 0 @@ -91,7 +146,7 @@ heat_level_2 = 480 //Default 400 heat_level_3 = 1100 //Default 1000 - flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL + flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SKIN_COLOR flesh_color = "#34AF10" @@ -115,7 +170,7 @@ primitive = /mob/living/carbon/monkey/tajara - flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL + flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SKIN_COLOR flesh_color = "#AFA59E" @@ -126,7 +181,7 @@ language = "Skrellian" primitive = /mob/living/carbon/monkey/skrell - flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR + flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR flesh_color = "#8CD7A3" @@ -144,15 +199,79 @@ cold_level_3 = 0 eyes = "vox_eyes_s" + breath_type = "nitrogen" + poison_type = "oxygen" flags = NO_SCAN | NO_BLOOD blood_color = "#2299FC" flesh_color = "#808D11" + sprite_sheets = list( + "suit" = 'icons/mob/species/vox/suit.dmi', + "head" = 'icons/mob/species/vox/head.dmi', + "mask" = 'icons/mob/species/vox/mask.dmi', + "feet" = 'icons/mob/species/vox/feet.dmi', + "gloves" = 'icons/mob/species/vox/gloves.dmi' + ) + /datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H) + H.verbs += /mob/living/carbon/human/proc/leap + ..() + +/datum/species/vox/armalis/handle_post_spawn(var/mob/living/carbon/human/H) + + H.verbs += /mob/living/carbon/human/proc/gut + ..() + +/datum/species/vox/armalis + name = "Vox Armalis" + icobase = 'icons/mob/human_races/r_armalis.dmi' + deform = 'icons/mob/human_races/r_armalis.dmi' + language = "Vox-pidgin" + attack_verb = "slash" + + warning_low_pressure = 50 + hazard_low_pressure = 0 + + cold_level_1 = 80 + cold_level_2 = 50 + cold_level_3 = 0 + + heat_level_1 = 2000 + heat_level_2 = 3000 + heat_level_3 = 4000 + + brute_mod = 0.2 + burn_mod = 0.2 + + eyes = "blank_eyes" + breath_type = "nitrogen" + poison_type = "oxygen" + + flags = NO_SCAN | NO_BLOOD | HAS_TAIL | NO_PAIN | IS_WHITELISTED + + blood_color = "#2299FC" + flesh_color = "#808D11" + + tail = "armalis_tail" + icon_template = 'icons/mob/human_races/r_armalis.dmi' + + sprite_sheets = list( + "suit" = 'icons/mob/species/armalis/suit.dmi', + "gloves" = 'icons/mob/species/armalis/gloves.dmi', + "feet" = 'icons/mob/species/armalis/feet.dmi', + "head" = 'icons/mob/species/armalis/head.dmi', + "held" = 'icons/mob/species/armalis/held.dmi' + ) + +/datum/species/vox/create_organs(var/mob/living/carbon/human/H) + + ..() //create organs first. + + //Now apply cortical stack. var/datum/organ/external/affected = H.get_organ("head") //To avoid duplicates. @@ -171,8 +290,6 @@ M.cortical_stacks += I M.raiders[H.mind] = I - return ..() - /datum/species/diona name = "Diona" icobase = 'icons/mob/human_races/r_diona.dmi' @@ -199,9 +316,10 @@ flesh_color = "#907E4A" /datum/species/diona/handle_post_spawn(var/mob/living/carbon/human/H) - H.gender = NEUTER + return ..() + /datum/species/diona/handle_death(var/mob/living/carbon/human/H) var/mob/living/carbon/monkey/diona/S = new(get_turf(H)) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 7f31d737..4447c5f2 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -211,6 +211,9 @@ O.emp_act(severity) ..() +/mob/living/proc/can_inject() + return 1 + /mob/living/proc/get_organ_target() var/mob/shooter = src var/t = shooter:zone_sel.selecting @@ -312,7 +315,7 @@ // make the icons look correct regenerate_icons() - + hud_updateflag |= 1 << HEALTH_HUD hud_updateflag |= 1 << STATUS_HUD return @@ -447,9 +450,23 @@ //Getting out of someone's inventory. if(istype(src.loc,/obj/item/weapon/holder)) - var/obj/item/weapon/holder/H = src.loc - src.loc = get_turf(src.loc) - del(H) + var/obj/item/weapon/holder/H = src.loc //Get our item holder. + var/mob/M = H.loc //Get our mob holder (if any). + + if(istype(M)) + M.drop_from_inventory(H) + M << "[H] wriggles out of your grip!" + src << "You wriggle out of [M]'s grip!" + else if(istype(H.loc,/obj/item)) + src << "You struggle free of [H.loc]." + H.loc = get_turf(H) + + if(istype(M)) + for(var/atom/A in M.contents) + if(istype(A,/mob/living/simple_animal/borer) || istype(A,/obj/item/weapon/holder)) + return + + M.status_flags &= ~PASSEMOTES return //Resisting control by an alien mind. @@ -582,6 +599,7 @@ sleep(10) SC.broken = 1 SC.locked = 0 + SC.update_icon() usr << "\red You successfully break out!" for(var/mob/O in viewers(L.loc)) O.show_message("\red \the [usr] successfully broke out of \the [SC]!", 1) @@ -591,6 +609,7 @@ SC.open() else C.welded = 0 + C.update_icon() usr << "\red You successfully break out!" for(var/mob/O in viewers(L.loc)) O.show_message("\red \the [usr] successfully broke out of \the [C]!", 1) @@ -685,7 +704,7 @@ resting = !resting src << "\blue You are now [resting ? "resting" : "getting up"]" -/mob/living/proc/handle_ventcrawl(var/obj/machinery/atmospherics/unary/vent_pump/vent_found = null) // -- TLE -- Merged by Carn +/mob/living/proc/handle_ventcrawl(var/obj/machinery/atmospherics/unary/vent_pump/vent_found = null, var/ignore_items = 0) // -- TLE -- Merged by Carn if(stat) src << "You must be conscious to do this!" return @@ -740,10 +759,12 @@ src << "Never mind, you left." return - for(var/obj/item/carried_item in contents)//If the monkey got on objects. - if( !istype(carried_item, /obj/item/weapon/implant) && !istype(carried_item, /obj/item/clothing/mask/facehugger) )//If it's not an implant or a facehugger - src << "\red You can't be carrying items or have items equipped when vent crawling!" - return + if(!ignore_items) + for(var/obj/item/carried_item in contents)//If the monkey got on objects. + if( !istype(carried_item, /obj/item/weapon/implant) && !istype(carried_item, /obj/item/clothing/mask/facehugger) )//If it's not an implant or a facehugger + src << "\red You can't be carrying items or have items equipped when vent crawling!" + return + if(isslime(src)) var/mob/living/carbon/slime/S = src if(S.Victim) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 28bf5240..7136c09a 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -58,7 +58,7 @@ return 2 if(!P.nodamage) apply_damage((P.damage/(absorb+1)), P.damage_type, def_zone, absorb, 0, P) - P.on_hit(src, absorb) + P.on_hit(src, absorb, def_zone) return absorb /mob/living/hitby(atom/movable/AM as mob|obj,var/speed = 5)//Standardization and logging -Sieve diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 3c32169f..4ba9f221 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -81,366 +81,54 @@ var/list/department_radio_keys = list( if(!istype(dongle)) return if(dongle.translate_binary) return 1 -/mob/living/say(var/message) - - /* - Formatting and sanitizing. - */ - - message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) - - /* - Sanity checking and speech failure. - */ - - if (!message) - return - - if(silent) - return - - if (stat == 2) // Dead. - return say_dead(message) - else if (stat) // Unconcious. - return - - if (src.client) - if(client.prefs.muted & MUTE_IC) - src << "\red You cannot speak in IC (muted)." - return - if (src.client.handle_spam_prevention(message, MUTE_IC)) - return - - // Mute disability - if (sdisabilities & MUTE) - return - - // Muzzled. - if (istype(wear_mask, /obj/item/clothing/mask/muzzle)) - return - - // Emotes. - if (copytext(message, 1, 2) == "*" && !stat) - return emote(copytext(message, 2)) - - /* - Identity hiding. - */ - var/alt_name = "" - if (istype(src, /mob/living/carbon/human) && name != GetVoice()) - var/mob/living/carbon/human/H = src - alt_name = " (as [H.get_id_name("Unknown")])" - - /* - Now we get into the real meat of the say processing. Determining the message mode. - */ - - var/italics = 0 - var/message_range = null - var/message_mode = null - var/datum/language/speaking = null //For use if a specific language is being spoken. - - var/braindam = getBrainLoss() - if (braindam >= 60) - if(prob(braindam/4)) - message = stutter(message) - if(prob(braindam)) - message = uppertext(message) - - // General public key. Special message handling - else if (copytext(message, 1, 2) == ";" || prob(braindam/2)) - if (ishuman(src)) - message_mode = "headset" - else if(ispAI(src) || isrobot(src)) - message_mode = "pAI" - message = copytext(message, 2) - // Begin checking for either a message mode or a language to speak. - else if (length(message) >= 2) - var/channel_prefix = copytext(message, 1, 3) - - //Check if the person is speaking a language that they know. - if(languages.len) - for(var/datum/language/L in languages) - if(lowertext(channel_prefix) == ":[L.key]") - speaking = L - break - message_mode = department_radio_keys[channel_prefix] - if (message_mode || speaking || copytext(message,1,2) == ":") - message = trim(copytext(message, 3)) - if (!(istype(src,/mob/living/carbon/human) || istype(src,/mob/living/carbon/monkey) || istype(src, /mob/living/simple_animal/parrot) || isrobot(src) && (message_mode=="department" || (message_mode in radiochannels)))) - message_mode = null //only humans can use headsets - - if(src.stunned > 2 || (traumatic_shock > 61 && prob(50))) - message_mode = null //Stunned people shouldn't be able to physically turn on their radio/hold down the button to speak into it - - message = capitalize(trim_left(message)) - - if (!message) - return - - if (stuttering) - message = stutter(message) - - var/list/obj/item/used_radios = new - var/is_speaking_radio = 0 - - switch (message_mode) - if ("headset") - if (src:l_ear && istype(src:l_ear,/obj/item/device/radio)) - src:l_ear.talk_into(src, message) - used_radios += src:l_ear - is_speaking_radio = 1 - else if (src:r_ear) - src:r_ear.talk_into(src, message) - used_radios += src:r_ear - is_speaking_radio = 1 - - message_range = 1 - italics = 1 - - if ("right ear") - if (src:r_ear) - src:r_ear.talk_into(src, message) - used_radios += src:r_ear - is_speaking_radio = 1 - - message_range = 1 - italics = 1 - - if ("left ear") - if (src:l_ear) - src:l_ear.talk_into(src, message) - used_radios += src:l_ear - is_speaking_radio = 1 - - message_range = 1 - italics = 1 - - if ("intercom") - for (var/obj/item/device/radio/intercom/I in view(1, null)) - I.talk_into(src, message) - used_radios += I - is_speaking_radio = 1 - - message_range = 1 - italics = 1 - - //I see no reason to restrict such way of whispering - if ("whisper") - whisper(message) - return - - if ("binary") - if(robot_talk_understand || binarycheck()) - //message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) //seems redundant - robot_talk(message) - return - - if ("alientalk") - if(alien_talk_understand || hivecheck()) - //message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) //seems redundant - alien_talk(message) - return - - if ("department") - if(istype(src, /mob/living/carbon)) - if (src:l_ear && istype(src:l_ear,/obj/item/device/radio)) - src:l_ear.talk_into(src, message, message_mode) - used_radios += src:l_ear - is_speaking_radio = 1 - if (src:r_ear) - src:r_ear.talk_into(src, message, message_mode) - used_radios += src:r_ear - is_speaking_radio = 1 - else if(istype(src, /mob/living/silicon/robot)) - if (src:radio) - src:radio.talk_into(src, message, message_mode) - used_radios += src:radio - message_range = 1 - italics = 1 - - if ("pAI") - if (src:radio) - src:radio.talk_into(src, message) - used_radios += src:radio - message_range = 1 - italics = 1 - - if("changeling") - if(mind && mind.changeling) - for(var/mob/Changeling in mob_list) - if((Changeling.mind && Changeling.mind.changeling) || istype(Changeling, /mob/dead/observer)) - Changeling << "[mind.changeling.changelingID]: [message]" - return -////SPECIAL HEADSETS START - else - //world << "SPECIAL HEADSETS" - if (message_mode in radiochannels) - if(isrobot(src))//Seperates robots to prevent runtimes from the ear stuff - var/mob/living/silicon/robot/R = src - if(R.radio)//Sanityyyy - R.radio.talk_into(src, message, message_mode) - used_radios += R.radio - else - if (src:l_ear && istype(src:l_ear,/obj/item/device/radio)) - src:l_ear.talk_into(src, message, message_mode) - used_radios += src:l_ear - else if (src:r_ear) - src:r_ear.talk_into(src, message, message_mode) - used_radios += src:r_ear - message_range = 1 - italics = 1 -/////SPECIAL HEADSETS END - - var/datum/gas_mixture/environment = loc.return_air() - if(environment) - var/pressure = environment.return_pressure() - if (pressure < SAY_MINIMUM_PRESSURE) //in space no one can hear you scream - italics = 1 - message_range = 1 - - var/list/listening - - listening = get_mobs_in_view(message_range, src) - var/list/onscreen = viewers() - for(var/mob/M in player_list) - if (!M.client) - continue //skip monkeys and leavers - if (istype(M, /mob/new_player)) - continue - if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_GHOSTEARS) && src.client) // src.client is so that ghosts don't have to listen to mice - listening|=M +/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/italics=0, var/message_range = world.view, var/list/used_radios = list()) var/turf/T = get_turf(src) - var/list/W = hear(message_range, T) - for (var/obj/O in ((W | contents)-used_radios)) - W |= O + var/list/listening = list() + if(T) - for (var/mob/M in W) - W |= M.contents + var/list/objects = list() + var/list/hear = hear(message_range, T) + var/list/hearturfs = list() - for (var/atom/A in W) - if(istype(A, /mob/living/simple_animal/parrot)) //Parrot speech mimickry - if(A == src) - continue //Dont imitate ourselves + for(var/I in hear) + if(istype(I, /mob/)) + var/mob/M = I + listening += M + hearturfs += M.locs[1] + for(var/obj/O in M.contents) + objects |= O + else if(istype(I, /obj/)) + var/obj/O = I + hearturfs += O.locs[1] + objects |= O + + for(var/mob/M in player_list) + if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS)) + listening |= M + continue + if(M.loc && M.locs[1] in hearturfs) + listening |= M - var/mob/living/simple_animal/parrot/P = A - if(P.speech_buffer.len >= 10) - P.speech_buffer.Remove(pick(P.speech_buffer)) - P.speech_buffer.Add(message) - - if(istype(A, /obj/)) //radios in pockets and backpacks work - var/obj/O = A - spawn (0) - if(O) - O.hear_talk(src, message) - - -/* Commented out as replaced by code above from BS12 - for (var/obj/O in ((V | contents)-used_radios)) //radio in pocket could work, radio in backpack wouldn't --rastaf0 - spawn (0) - if (O) - O.hear_talk(src, message) -*/ - -/* if(isbrain(src))//For brains to properly talk if they are in an MMI..or in a brain. Could be extended to other mobs I guess. - for(var/obj/O in loc)//Kinda ugly but whatever. - if(O) - spawn(0) - O.hear_talk(src, message) -*/ - - - var/list/heard_a = list() // understood us - var/list/heard_b = list() // didn't understand us - - for (var/M in listening) - if(hascall(M,"say_understands")) - if (M:say_understands(src,speaking)) - heard_a += M - else - heard_b += M - else - heard_a += M + for(var/obj/O in objects) + spawn(0) + O.hear_talk(src, message, verb, speaking) var/speech_bubble_test = say_test(message) var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]") spawn(30) del(speech_bubble) - for(var/mob/M in hearers(5, src)) - if(M != src && is_speaking_radio) - M:show_message("[src] talks into [used_radios.len ? used_radios[1] : "radio"]") - - var/rendered = null - - if (length(heard_a)) - var/message_a = say_quote(message,speaking) - - if (italics) - message_a = "[message_a]" - - var/message_ghost = "[message_a]" // bold so ghosts know the person is in view. - rendered = "[GetVoice()][alt_name] [message_a]" - var/rendered_ghost = "[GetVoice()][alt_name] [message_ghost]" - for (var/mob/M in heard_a) - if(M.client) - if(hascall(M,"show_message")) - var/deaf_message = "" - var/deaf_type = 1 - if(M != src) - deaf_message = "[name][alt_name] talks but you cannot hear them." - else - deaf_message = "You cannot hear yourself!" - deaf_type = 2 // Since you should be able to hear yourself without looking - if (M.stat == DEAD && (M.client.prefs.toggles & CHAT_GHOSTEARS) && M in onscreen) - M:show_message(rendered_ghost, 2, deaf_message, deaf_type) - else - M:show_message(rendered, 2, deaf_message, deaf_type) - M << speech_bubble - - if (length(heard_b)) - - var/message_b - message_b = stars(message) - message_b = say_quote(message_b,speaking) - - if (italics) - message_b = "[message_b]" - - rendered = "[name][alt_name] [message_b]" //Voice_name isn't too useful. You'd be able to tell who was talking presumably. + if(used_radios.len) + for(var/mob/living/M in hearers(5, src)) + if(M != src) + M.show_message("[src] talks into [used_radios.len ? used_radios[1] : "radio"]") - for (var/M in heard_b) - if(hascall(M,"show_message")) - M:show_message(rendered, 2) - M << speech_bubble + for(var/mob/M in listening) + M << speech_bubble + M.hear_say(message,verb,speaking,alt_name, italics, src) - /* - if(M.client) - - if(!M.client.bubbles || M == src) - var/image/I = image('icons/effects/speechbubble.dmi', B, "override") - I.override = 1 - M << I - */ /* - - flick("[presay]say", B) - - if(istype(loc, /turf)) - B.loc = loc - else - B.loc = loc.loc - - spawn() - sleep(11) - del(B) - */ - - //talking items - for(var/obj/item/weapon/O in view(3,src)) - if(O.listening_to_players) - O.catchMessage(message, src) log_say("[name]/[key] : [message]") @@ -449,5 +137,3 @@ var/list/department_radio_keys = list( /mob/living/proc/GetVoice() return name - - diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index f13b1ab5..0fa2b9a9 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -24,7 +24,6 @@ var/list/ai_list = list() var/list/connected_robots = list() var/aiRestorePowerRoutine = 0 //var/list/laws = list() - var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list()) var/viewalerts = 0 var/lawcheck[1] var/ioncheck[1] @@ -94,7 +93,7 @@ var/list/ai_list = list() /mob/living/silicon/ai/proc/ai_camera_list, /mob/living/silicon/ai/proc/ai_network_change, \ /mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \ /mob/living/silicon/ai/proc/toggle_camera_light) - + if(!safety)//Only used by AIize() to successfully spawn an AI. if (!B)//If there is no player/brain inside. @@ -146,7 +145,7 @@ var/list/ai_list = list() /obj/machinery/ai_powersupply name="Power Supply" active_power_usage=1000 - use_power = 2 + use_power = 2 power_channel = EQUIP var/mob/living/silicon/ai/powered_ai = null invisibility = 100 @@ -155,12 +154,12 @@ var/list/ai_list = list() powered_ai = ai if(isnull(powered_ai)) Del() - + loc = powered_ai.loc use_power(1) // Just incase we need to wake up the power system. ..() - + /obj/machinery/ai_powersupply/process() if(!powered_ai || powered_ai.stat & DEAD) Del() @@ -237,26 +236,20 @@ var/list/ai_list = list() dat += "Close

        " for (var/cat in alarms) dat += text("[]
        \n", cat) - var/list/L = alarms[cat] - if (L.len) - for (var/alarm in L) - var/list/alm = L[alarm] - var/area/A = alm[1] - var/C = alm[2] - var/list/sources = alm[3] + var/list/alarmlist = alarms[cat] + if (alarmlist.len) + for (var/area_name in alarmlist) + var/datum/alarm/alarm = alarmlist[area_name] dat += "" - if (C && istype(C, /list)) - var/dat2 = "" - for (var/obj/machinery/camera/I in C) - dat2 += text("[][]", (dat2=="") ? "" : " | ", src, I, I.c_tag) - dat += text("-- [] ([])", A.name, (dat2!="") ? dat2 : "No Camera") - else if (C && istype(C, /obj/machinery/camera)) - var/obj/machinery/camera/Ctmp = C - dat += text("-- [] ([])", A.name, src, C, Ctmp.c_tag) - else - dat += text("-- [] (No Camera)", A.name) - if (sources.len > 1) - dat += text("- [] sources", sources.len) + + var/cameratext = "" + if (alarm.cameras) + for (var/obj/machinery/camera/I in alarm.cameras) + cameratext += text("[][]", (cameratext=="") ? "" : " | ", src, I, I.c_tag) + dat += text("-- [] ([])", alarm.area.name, (cameratext)? cameratext : "No Camera") + + if (alarm.sources.len > 1) + dat += text(" - [] sources", alarm.sources.len) dat += "
        \n" else dat += "-- All Systems Nominal
        \n" @@ -405,9 +398,23 @@ var/list/ai_list = list() if (href_list["track"]) var/mob/target = locate(href_list["track"]) in mob_list +/* var/mob/living/silicon/ai/A = locate(href_list["track2"]) in mob_list if(A && target) A.ai_actual_track(target) +*/ + + //Strip off any "(as Derplord)". + //If there's a way to do this via a var that doesn't give the AI extra info, please let me know. + var/seeking = target.name + var/index = findtext(seeking, "(as ") + if(index) + seeking = copytext(seeking, 1, index-1) + + if(target && html_decode(href_list["trackname"]) == seeking) + ai_actual_track(target) + else + src << "\red System error. Cannot locate [html_decode(href_list["trackname"])]." return else if (href_list["faketrack"]) @@ -520,59 +527,28 @@ var/list/ai_list = list() return 1 -/mob/living/silicon/ai/triggerAlarm(var/class, area/A, var/O, var/alarmsource) +/mob/living/silicon/ai/triggerAlarm(var/class, area/A, list/cameralist, var/source) if (stat == 2) return 1 - var/list/L = alarms[class] - for (var/I in L) - if (I == A.name) - var/list/alarm = L[I] - var/list/sources = alarm[3] - if (!(alarmsource in sources)) - sources += alarmsource - return 1 - var/obj/machinery/camera/C = null - var/list/CL = null - if (O && istype(O, /list)) - CL = O - if (CL.len == 1) - C = CL[1] - else if (O && istype(O, /obj/machinery/camera)) - C = O - L[A.name] = list(A, (C) ? C : O, list(alarmsource)) - if (O) - if (C && C.can_use()) - queueAlarm("--- [class] alarm detected in [A.name]! ([C.c_tag])", class) - else if (CL && CL.len) - var/foo = 0 - var/dat2 = "" - for (var/obj/machinery/camera/I in CL) - dat2 += text("[][]", (!foo) ? "" : " | ", src, I, I.c_tag) //I'm not fixing this shit... - foo = 1 - queueAlarm(text ("--- [] alarm detected in []! ([])", class, A.name, dat2), class) - else - queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class) - else - queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class) + + ..() + + var/cameratext = "" + for (var/obj/machinery/camera/C in cameralist) + cameratext += "[(cameratext == "")? "" : "|"][C.c_tag]" + + queueAlarm("--- [class] alarm detected in [A.name]! ([(cameratext)? cameratext : "No Camera"])", class) + if (viewalerts) ai_alerts() - return 1 -/mob/living/silicon/ai/cancelAlarm(var/class, area/A as area, obj/origin) - var/list/L = alarms[class] - var/cleared = 0 - for (var/I in L) - if (I == A.name) - var/list/alarm = L[I] - var/list/srcs = alarm[3] - if (origin in srcs) - srcs -= origin - if (srcs.len == 0) - cleared = 1 - L -= I - if (cleared) +/mob/living/silicon/ai/cancelAlarm(var/class, area/A as area, var/source) + var/has_alarm = ..() + + if (!has_alarm) queueAlarm(text("--- [] alarm in [] has been cleared.", class, A.name), class, 0) if (viewalerts) ai_alerts() - return !cleared + + return has_alarm /mob/living/silicon/ai/cancel_camera() set category = "AI Commands" diff --git a/code/modules/mob/living/silicon/alarm.dm b/code/modules/mob/living/silicon/alarm.dm new file mode 100644 index 00000000..ee505fae --- /dev/null +++ b/code/modules/mob/living/silicon/alarm.dm @@ -0,0 +1,111 @@ +/datum/alarm + var/area/area //the area associated with the alarm. Used to identify the alarm + var/list/sources //list of things triggering the alarm. Used to determine when the alarm should be cleared. + var/list/cameras //list of cameras that can be switched to, if the player has that capability. + +/datum/alarm/New(area/A, list/sourcelist=list(), list/cameralist=list()) + area = A + sources = sourcelist + cameras = cameralist + +/mob/living/silicon + var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list()) //each sublist stores alarms keyed by the area name + var/list/alarms_to_show = list() + var/list/alarms_to_clear = list() + var/list/alarm_types_show = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0) + var/list/alarm_types_clear = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0) + +/mob/living/silicon/proc/triggerAlarm(var/class, area/A, list/cameralist, var/source) + var/list/alarmlist = alarms[class] + + //see if there is already an alarm of this class for this area + if (A.name in alarmlist) + var/datum/alarm/existing = alarmlist[A.name] + existing.sources += source + existing.cameras |= cameralist + else + alarmlist[A.name] = new /datum/alarm(A, list(source), cameralist) + +/mob/living/silicon/proc/cancelAlarm(var/class, area/A as area, var/source) + var/cleared = 0 + var/list/alarmlist = alarms[class] + + if (A.name in alarmlist) + var/datum/alarm/alarm = alarmlist[A.name] + alarm.sources -= source + + if (!(alarm.sources.len)) + cleared = 1 + alarmlist -= A.name + + return !cleared + +/mob/living/silicon/proc/queueAlarm(var/message, var/type, var/incoming = 1) + var/in_cooldown = (alarms_to_show.len > 0 || alarms_to_clear.len > 0) + if(incoming) + alarms_to_show += message + alarm_types_show[type] += 1 + else + alarms_to_clear += message + alarm_types_clear[type] += 1 + + if(!in_cooldown) + spawn(10 * 10) // 10 seconds + + if(alarms_to_show.len < 5) + for(var/msg in alarms_to_show) + src << msg + else if(alarms_to_show.len) + + var/msg = "--- " + + if(alarm_types_show["Motion"]) + msg += "MOTION: [alarm_types_show["Motion"]] alarms detected. - " + + if(alarm_types_show["Fire"]) + msg += "FIRE: [alarm_types_show["Fire"]] alarms detected. - " + + if(alarm_types_show["Atmosphere"]) + msg += "ATMOSPHERE: [alarm_types_show["Atmosphere"]] alarms detected. - " + + if(alarm_types_show["Power"]) + msg += "POWER: [alarm_types_show["Power"]] alarms detected. - " + + if(alarm_types_show["Camera"]) + msg += "CAMERA: [alarm_types_show["Power"]] alarms detected. - " + + msg += "\[Show Alerts\]" + src << msg + + if(alarms_to_clear.len < 3) + for(var/msg in alarms_to_clear) + src << msg + + else if(alarms_to_clear.len) + var/msg = "--- " + + if(alarm_types_clear["Motion"]) + msg += "MOTION: [alarm_types_clear["Motion"]] alarms cleared. - " + + if(alarm_types_clear["Fire"]) + msg += "FIRE: [alarm_types_clear["Fire"]] alarms cleared. - " + + if(alarm_types_clear["Atmosphere"]) + msg += "ATMOSPHERE: [alarm_types_clear["Atmosphere"]] alarms cleared. - " + + if(alarm_types_clear["Power"]) + msg += "POWER: [alarm_types_clear["Power"]] alarms cleared. - " + + if(alarm_types_show["Camera"]) + msg += "CAMERA: [alarm_types_show["Power"]] alarms detected. - " + + msg += "\[Show Alerts\]" + src << msg + + + alarms_to_show = list() + alarms_to_clear = list() + for(var/i = 1; i < alarm_types_show.len; i++) + alarm_types_show[i] = 0 + for(var/i = 1; i < alarm_types_clear.len; i++) + alarm_types_clear[i] = 0 \ No newline at end of file diff --git a/code/modules/mob/living/silicon/pai/examine.dm b/code/modules/mob/living/silicon/pai/examine.dm index d1b272f5..4780e6ae 100644 --- a/code/modules/mob/living/silicon/pai/examine.dm +++ b/code/modules/mob/living/silicon/pai/examine.dm @@ -1,5 +1,5 @@ /mob/living/silicon/pai/examine() //removed as it was pointless...moved to the pai-card instead. - /* This is totaly pointless because this mob is contained inside a card! + /* This is totally pointless because this mob is contained inside a card! set src in oview() var/msg = "*---------*\nThis is \icon[src] \a [src]!\n" diff --git a/code/modules/mob/living/silicon/pai/life.dm b/code/modules/mob/living/silicon/pai/life.dm index df84d226..78441fe1 100644 --- a/code/modules/mob/living/silicon/pai/life.dm +++ b/code/modules/mob/living/silicon/pai/life.dm @@ -5,7 +5,7 @@ if(get_dist(src, src.cable) > 1) var/turf/T = get_turf_or_move(src.loc) for (var/mob/M in viewers(T)) - M.show_message("\red [src.cable] rapidly retracts back into its spool.", 3, "\red You hear a click and the sound of wire spooling rapidly.", 2) + M.show_message("\red The data cable rapidly retracts back into its spool.", 3, "\red You hear a click and the sound of wire spooling rapidly.", 2) del(src.cable) regular_hud_updates() diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm index 2e9b6b40..5b23b7f7 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -110,42 +110,118 @@ var/datum/paiController/paiController // Global handler for pAI candidates var/dat = "" dat += {" "} - dat += {"

        Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you!

        - - - + dat += {" + + pAI Personality Configuration +

        Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you!

        - - +
        Name:[candidate.name]
        \[Edit\]What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.
        Description:[candidate.description]
        \[Edit\]What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        Name:[candidate.name] 
        What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.
        Description:[candidate.description] 
        What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.
        Preferred Role:[candidate.role] 
        Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.
        OOC Comments:[candidate.comments] 
        Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want.
        +
        + + + + + + + +
        + Save Personality +
        + Load Personality +

        + + +
        Submit Personality

        -
        Preferred Role:[candidate.role]
        \[Edit\]Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.
        OOC Comments:[candidate.comments]
        \[Edit\]Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want.
        " - -
        -

        Submit Personality


        - Save Personality
        - Load Personality
        "} - - M << browse(dat, "window=paiRecruit") + M << browse(dat, "window=paiRecruit;size=580x580;") proc/findPAI(var/obj/item/device/paicard/p, var/mob/user) requestRecruits() @@ -161,35 +237,105 @@ var/datum/paiController/paiController // Global handler for pAI candidates var/dat = "" dat += {" - - "} - dat += "

        Requesting AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.

        " - - dat += "" + + + + + + + pAI Availability List

        + "} + dat += "

        Displaying available AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.

        " for(var/datum/paiCandidate/c in available) - dat += {" - - - - "} + dat += {" +
        Name:[c.name]
        Description:[c.description]
        Preferred Role:[c.role]
        OOC Comments:[c.comments]
        \[Download [c.name]\]
        + + + + + + + + + + + + + + + + +
        Name:[c.name]
        Description:[c.description]
        Preferred Role:[c.role]
        OOC Comments:[c.comments]
        + + +
        Download [c.name] +
        +
        + "} - dat += "" + dat += {" + + + "} user << browse(dat, "window=findPai") diff --git a/code/modules/mob/living/silicon/pai/say.dm b/code/modules/mob/living/silicon/pai/say.dm index 4cb39b0c..6f6af4bb 100644 --- a/code/modules/mob/living/silicon/pai/say.dm +++ b/code/modules/mob/living/silicon/pai/say.dm @@ -1,5 +1,5 @@ /mob/living/silicon/pai/say(var/msg) if(silence_time) - src << "Communication circuits remain unitialized." + src << "Communication circuits remain uninitialized." else ..(msg) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 6d7646f7..3ee1b824 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -33,7 +33,7 @@ if(temp) left_part = temp else if(src.stat == 2) // Show some flavor text if the pAI is dead - left_part = "ÈRrÖR Ða†Ä ÇÖRrÚþ†Ìoñ" + left_part = "ÈRrÖR Ða†Ä ÇÖRrÚþ†Ìoñ" //This file has to be saved as ANSI or this will not display correctly right_part = "
        Program index hash not found
        " else @@ -66,31 +66,34 @@ left_part = src.softwareCamera() if("signaller") left_part = src.softwareSignal() + if("radio") + left_part = src.softwareRadio() //usr << browse_rsc('windowbak.png') // This has been moved to the mob's Login() proc - // Declaring a doctype is necessary to enable BYOND's crappy browser's more advanced CSS functionality + // Declaring a doctype is necessary to enable BYOND's crappy browser's more advanced CSS functionality dat = {"